diff --git a/README.md b/README.md index dec13f6..d04cc78 100644 --- a/README.md +++ b/README.md @@ -52,22 +52,6 @@ minimum number of milliseconds between two events to be considered slow. It defaults to 200 ms. -## Disable the native mouse pointer - -The Shuttle acts as a mouse when you plug it into Ubuntu. Disable it with: - - $ xinput --list - "Virtual core pointer" id=0 [XPointer] - "Virtual core keyboard" id=1 [XKeyboard] - "Keyboard2" id=2 [XExtensionKeyboard] - "Mouse2" id=3 [XExtensionKeyboard] - - # Disable with: - $ xinput disable 2 - -Ref: https://unix.stackexchange.com/questions/91075/how-to-disable-keyboard - - ## Run With: @@ -75,20 +59,43 @@ With: sudo shuttle-go /dev/input/by-id/usb-Contour_Design_ShuttlePRO_v2-event-if00 +## Install in `udev` with: + +As root, write in the file `/etc/udev/rules.d/01-shuttle-go.rules`: + + ACTION=="add", ATTRS{name}=="Contour Design ShuttlePRO v2", ENV{MINOR}=="79", RUN+="/home/abourget/go/src/github.com/abourget/shuttle-go/udev-start.sh" + ACTION=="remove", ATTRS{name}=="Contour Design ShuttlePRO v2", RUN+="/usr/bin/pkill shuttle-go" + +Then run: + + udevadm control --reload-rules && udevadm trigger + +Your device should not be plug-and-play. + +WARNING: this will be executed as ROOT when the device is plugged. If +someone can write to that `udev-start.sh` file or anything that is run +by that script (`shuttle-go` for example), this could lead to +privilege escalation. + +If you prefer running `shuttle-go` manually from a terminal, you can change the `ACTION=="add"` line above to: + + ACTION=="add", ATTRS{name}=="Contour Design ShuttlePRO v2", MODE="0644" + +This will grant non-root access to the device, so you can run +`shuttle-go` and see its logs. + + ## License MIT -##TODO +## TODO * Don't require `xdotool` - * Use xgb's `xtest` package and send the FakeInput directly there.. should work - a lot better. - * Document in here all the keys that are work and their proper syntax. Add a few helpers. + * Use xgb's `xtest` package and send the FakeInput directly there.. + +* Document in here all the keys that are work and their proper syntax. Add a few helpers. * Watch the configuration file, and reload on change. -* Check udev, DISPLAY=:0.0 to start ? - * Retry ? Check the error message going out. - * Have a default SlowJog configuration. diff --git a/config.go b/config.go index 9157048..f2c8b21 100644 --- a/config.go +++ b/config.go @@ -54,11 +54,13 @@ type deviceBinding struct { holdButtons []string pressButton string original string + description string } func (ac *AppConfig) parseBindings() error { for key, value := range ac.Bindings { - newBinding := &deviceBinding{heldButtons: make(map[int]bool), original: value} + binding, description := bindingAndDescription(value) + newBinding := &deviceBinding{heldButtons: make(map[int]bool), original: binding, description: description} // Input input := strings.Split(key, "+") @@ -106,6 +108,16 @@ func (ac *AppConfig) parseBindings() error { return nil } +var descriptionRE = regexp.MustCompile(`([^/]*)(\s*// *(.+))?`) + +func bindingAndDescription(input string) (string, string) { + matches := descriptionRE.FindStringSubmatch(input) + if matches == nil { + return input, "" + } + return strings.TrimSpace(matches[1]), strings.TrimSpace(matches[3]) +} + func LoadConfig(filename string) error { cnt, err := ioutil.ReadFile(filename) if err != nil { diff --git a/config_test.go b/config_test.go new file mode 100644 index 0000000..4d5cc7c --- /dev/null +++ b/config_test.go @@ -0,0 +1,26 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBindingAndDescription(t *testing.T) { + tests := []struct { + in string + bind, desc string + }{ + {"Ctrl+A", "Ctrl+A", ""}, + {"Ctrl+A // ", "Ctrl+A", ""}, + {"Ctrl+A // Description", "Ctrl+A", "Description"}, + {"Ctrl+A//Description", "Ctrl+A", "Description"}, + {"Ctrl+A // Description", "Ctrl+A", "Description"}, + } + + for idx, test := range tests { + bind, desc := bindingAndDescription(test.in) + assert.Equal(t, test.bind, bind, "%d", idx) + assert.Equal(t, test.desc, desc, "%d", idx) + } +} diff --git a/main.go b/main.go index 0b30e6c..145082e 100644 --- a/main.go +++ b/main.go @@ -12,17 +12,28 @@ import ( ) var configFile = flag.String("config", filepath.Join(os.Getenv("HOME"), ".shuttle-go.json"), "Location to the .shuttle-go.json configuration") +var logFile = flag.String("log-file", "", "Log to a file instead of stdout") func main() { flag.Parse() - if len(flag.Args()) != 1 { - fmt.Println("Missing device name as parameter.\nExample: [program] /dev/input/by-id/usb-Contour_Design_ShuttlePRO_v2-event-if00\n") - os.Exit(1) + if *logFile != "" { + log, err := os.Create(*logFile) + if err != nil { + os.Exit(101) + } + defer log.Close() + os.Stderr = log + os.Stdout = log } - err := LoadConfig(*configFile) - if err != nil { + devicePath := "/dev/input/by-id/usb-Contour_Design_ShuttlePRO_v2-event-if00" + if len(flag.Args()) == 1 { + devicePath = flag.Arg(0) + } + fmt.Println("Using device", devicePath) + + if err := LoadConfig(*configFile); err != nil { fmt.Println("Error reading configuration:", err) os.Exit(10) } @@ -45,7 +56,7 @@ func main() { } // Shuttle device event receiver - dev, err := evdev.Open(flag.Arg(0)) + dev, err := evdev.Open(devicePath) if err != nil { fmt.Println("Couldn't open Shuttle device:", err) os.Exit(2) @@ -57,6 +68,7 @@ func main() { for { if err := mapper.Process(); err != nil { fmt.Println("Error processing input events (continuing):", err) + os.Exit(123) } } diff --git a/mapper.go b/mapper.go index e241d9f..789895d 100644 --- a/mapper.go +++ b/mapper.go @@ -163,7 +163,7 @@ func (m *Mapper) EmitKeys(modifiers map[int]bool, keyDown int) error { } func (m *Mapper) executeBinding(binding *deviceBinding) error { - time.Sleep(100 * time.Millisecond) + time.Sleep(25 * time.Millisecond) // cookie := xtest.FakeInputChecked(m.watcher.conn, 2, 0x7b00, 0, m.watcher.lastWindowID, 0, 0, 0x00) // if err := cookie.Check(); err != nil { diff --git a/udev-start.sh b/udev-start.sh new file mode 100755 index 0000000..913132f --- /dev/null +++ b/udev-start.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +export HOME=/home/abourget + +# Only the "event" input device, not the "mouse" device (where MINOR=34) +if [ $MINOR != "79" ]; then exit 99; fi + +#LOGFILE=/tmp/shuttle-`basename $DEVNAME`.env +#env > $LOGFILE + +export XAUTHORITY=$HOME/.Xauthority +export DISPLAY=:0.0 +export PATH=/usr/bin # which includes the path to `xdotool` + +$HOME/go/bin/shuttle-go -config $HOME/.shuttle-go.json -log-file /tmp/shuttle-go.log $DEVNAME diff --git a/vendor/github.com/BurntSushi/xgb/AUTHORS b/vendor/github.com/BurntSushi/xgb/AUTHORS new file mode 100644 index 0000000..08fc0cd --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/AUTHORS @@ -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 +# The email address is not required for organizations. + +# Please keep the list sorted. + +Anthony Martin +Firmansyah Adiputra +Google Inc. +Scott Lawrence +Tor Andersson diff --git a/vendor/github.com/BurntSushi/xgb/CONTRIBUTORS b/vendor/github.com/BurntSushi/xgb/CONTRIBUTORS new file mode 100644 index 0000000..46dc4b0 --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/CONTRIBUTORS @@ -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 + +# Please keep the list sorted. + +Anthony Martin +Firmansyah Adiputra +Ian Lance Taylor +Nigel Tao +Robert Griesemer +Russ Cox +Scott Lawrence +Tor Andersson diff --git a/vendor/github.com/BurntSushi/xgb/LICENSE b/vendor/github.com/BurntSushi/xgb/LICENSE new file mode 100644 index 0000000..d99cd90 --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/LICENSE @@ -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. diff --git a/vendor/github.com/BurntSushi/xgb/Makefile b/vendor/github.com/BurntSushi/xgb/Makefile new file mode 100644 index 0000000..7a3dae2 --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/Makefile @@ -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 + diff --git a/vendor/github.com/BurntSushi/xgb/README b/vendor/github.com/BurntSushi/xgb/README new file mode 100644 index 0000000..c96a5fb --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/README @@ -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 + diff --git a/vendor/github.com/BurntSushi/xgb/STYLE b/vendor/github.com/BurntSushi/xgb/STYLE new file mode 100644 index 0000000..b827c3c --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/STYLE @@ -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. + diff --git a/vendor/github.com/BurntSushi/xgb/auth.go b/vendor/github.com/BurntSushi/xgb/auth.go new file mode 100644 index 0000000..ec51d10 --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/auth.go @@ -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 +} diff --git a/vendor/github.com/BurntSushi/xgb/conn.go b/vendor/github.com/BurntSushi/xgb/conn.go new file mode 100644 index 0000000..1b7d838 --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/conn.go @@ -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 +} diff --git a/vendor/github.com/BurntSushi/xgb/cookie.go b/vendor/github.com/BurntSushi/xgb/cookie.go new file mode 100644 index 0000000..d5cdb29 --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/cookie.go @@ -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 + } +} diff --git a/vendor/github.com/BurntSushi/xgb/doc.go b/vendor/github.com/BurntSushi/xgb/doc.go new file mode 100644 index 0000000..64540e9 --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/doc.go @@ -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 diff --git a/vendor/github.com/BurntSushi/xgb/help.go b/vendor/github.com/BurntSushi/xgb/help.go new file mode 100644 index 0000000..f692442 --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/help.go @@ -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<> 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 +} diff --git a/vendor/github.com/BurntSushi/xgb/sync.go b/vendor/github.com/BurntSushi/xgb/sync.go new file mode 100644 index 0000000..59d0de1 --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/sync.go @@ -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 +} diff --git a/vendor/github.com/BurntSushi/xgb/xgb.go b/vendor/github.com/BurntSushi/xgb/xgb.go new file mode 100644 index 0000000..3d2c61f --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/xgb.go @@ -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 + } +} diff --git a/vendor/github.com/BurntSushi/xgb/xproto/xproto.go b/vendor/github.com/BurntSushi/xgb/xproto/xproto.go new file mode 100644 index 0000000..716c49b --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/xproto/xproto.go @@ -0,0 +1,14910 @@ +// Package xproto is the X client API for the extension. +package xproto + +// This file is automatically generated from xproto.xml. Edit at your peril! + +import ( + "github.com/BurntSushi/xgb" +) + +// Setup parses the setup bytes retrieved when +// connecting into a SetupInfo struct. +func Setup(c *xgb.Conn) *SetupInfo { + setup := new(SetupInfo) + SetupInfoRead(c.SetupBytes, setup) + return setup +} + +// DefaultScreen gets the default screen info from SetupInfo. +func (s *SetupInfo) DefaultScreen(c *xgb.Conn) *ScreenInfo { + return &s.Roots[c.DefaultScreen] +} + +// BadAccess is the error number for a BadAccess. +const BadAccess = 10 + +type AccessError RequestError + +// AccessErrorNew constructs a AccessError value that implements xgb.Error from a byte slice. +func AccessErrorNew(buf []byte) xgb.Error { + v := AccessError(RequestErrorNew(buf).(RequestError)) + v.NiceName = "Access" + return v +} + +// SequenceId returns the sequence id attached to the BadAccess error. +// This is mostly used internally. +func (err AccessError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadAccess error. If no bad value exists, 0 is returned. +func (err AccessError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadAccess error. +func (err AccessError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadAccess {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[10] = AccessErrorNew +} + +const ( + AccessControlDisable = 0 + AccessControlEnable = 1 +) + +// BadAlloc is the error number for a BadAlloc. +const BadAlloc = 11 + +type AllocError RequestError + +// AllocErrorNew constructs a AllocError value that implements xgb.Error from a byte slice. +func AllocErrorNew(buf []byte) xgb.Error { + v := AllocError(RequestErrorNew(buf).(RequestError)) + v.NiceName = "Alloc" + return v +} + +// SequenceId returns the sequence id attached to the BadAlloc error. +// This is mostly used internally. +func (err AllocError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadAlloc error. If no bad value exists, 0 is returned. +func (err AllocError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadAlloc error. +func (err AllocError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadAlloc {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[11] = AllocErrorNew +} + +const ( + AllowAsyncPointer = 0 + AllowSyncPointer = 1 + AllowReplayPointer = 2 + AllowAsyncKeyboard = 3 + AllowSyncKeyboard = 4 + AllowReplayKeyboard = 5 + AllowAsyncBoth = 6 + AllowSyncBoth = 7 +) + +type Arc struct { + X int16 + Y int16 + Width uint16 + Height uint16 + Angle1 int16 + Angle2 int16 +} + +// ArcRead reads a byte slice into a Arc value. +func ArcRead(buf []byte, v *Arc) int { + b := 0 + + v.X = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Width = xgb.Get16(buf[b:]) + b += 2 + + v.Height = xgb.Get16(buf[b:]) + b += 2 + + v.Angle1 = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Angle2 = int16(xgb.Get16(buf[b:])) + b += 2 + + return b +} + +// ArcReadList reads a byte slice into a list of Arc values. +func ArcReadList(buf []byte, dest []Arc) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Arc{} + b += ArcRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Arc value to a byte slice. +func (v Arc) Bytes() []byte { + buf := make([]byte, 12) + b := 0 + + xgb.Put16(buf[b:], uint16(v.X)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Y)) + b += 2 + + xgb.Put16(buf[b:], v.Width) + b += 2 + + xgb.Put16(buf[b:], v.Height) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Angle1)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Angle2)) + b += 2 + + return buf[:b] +} + +// ArcListBytes writes a list of Arc values to a byte slice. +func ArcListBytes(buf []byte, list []Arc) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +const ( + ArcModeChord = 0 + ArcModePieSlice = 1 +) + +type Atom uint32 + +func NewAtomId(c *xgb.Conn) (Atom, error) { + id, err := c.NewId() + if err != nil { + return 0, err + } + return Atom(id), nil +} + +const ( + AtomNone = 0 + AtomAny = 0 + AtomPrimary = 1 + AtomSecondary = 2 + AtomArc = 3 + AtomAtom = 4 + AtomBitmap = 5 + AtomCardinal = 6 + AtomColormap = 7 + AtomCursor = 8 + AtomCutBuffer0 = 9 + AtomCutBuffer1 = 10 + AtomCutBuffer2 = 11 + AtomCutBuffer3 = 12 + AtomCutBuffer4 = 13 + AtomCutBuffer5 = 14 + AtomCutBuffer6 = 15 + AtomCutBuffer7 = 16 + AtomDrawable = 17 + AtomFont = 18 + AtomInteger = 19 + AtomPixmap = 20 + AtomPoint = 21 + AtomRectangle = 22 + AtomResourceManager = 23 + AtomRgbColorMap = 24 + AtomRgbBestMap = 25 + AtomRgbBlueMap = 26 + AtomRgbDefaultMap = 27 + AtomRgbGrayMap = 28 + AtomRgbGreenMap = 29 + AtomRgbRedMap = 30 + AtomString = 31 + AtomVisualid = 32 + AtomWindow = 33 + AtomWmCommand = 34 + AtomWmHints = 35 + AtomWmClientMachine = 36 + AtomWmIconName = 37 + AtomWmIconSize = 38 + AtomWmName = 39 + AtomWmNormalHints = 40 + AtomWmSizeHints = 41 + AtomWmZoomHints = 42 + AtomMinSpace = 43 + AtomNormSpace = 44 + AtomMaxSpace = 45 + AtomEndSpace = 46 + AtomSuperscriptX = 47 + AtomSuperscriptY = 48 + AtomSubscriptX = 49 + AtomSubscriptY = 50 + AtomUnderlinePosition = 51 + AtomUnderlineThickness = 52 + AtomStrikeoutAscent = 53 + AtomStrikeoutDescent = 54 + AtomItalicAngle = 55 + AtomXHeight = 56 + AtomQuadWidth = 57 + AtomWeight = 58 + AtomPointSize = 59 + AtomResolution = 60 + AtomCopyright = 61 + AtomNotice = 62 + AtomFontName = 63 + AtomFamilyName = 64 + AtomFullName = 65 + AtomCapHeight = 66 + AtomWmClass = 67 + AtomWmTransientFor = 68 +) + +// BadAtom is the error number for a BadAtom. +const BadAtom = 5 + +type AtomError ValueError + +// AtomErrorNew constructs a AtomError value that implements xgb.Error from a byte slice. +func AtomErrorNew(buf []byte) xgb.Error { + v := AtomError(ValueErrorNew(buf).(ValueError)) + v.NiceName = "Atom" + return v +} + +// SequenceId returns the sequence id attached to the BadAtom error. +// This is mostly used internally. +func (err AtomError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadAtom error. If no bad value exists, 0 is returned. +func (err AtomError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadAtom error. +func (err AtomError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadAtom {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[5] = AtomErrorNew +} + +const ( + AutoRepeatModeOff = 0 + AutoRepeatModeOn = 1 + AutoRepeatModeDefault = 2 +) + +const ( + BackPixmapNone = 0 + BackPixmapParentRelative = 1 +) + +const ( + BackingStoreNotUseful = 0 + BackingStoreWhenMapped = 1 + BackingStoreAlways = 2 +) + +const ( + BlankingNotPreferred = 0 + BlankingPreferred = 1 + BlankingDefault = 2 +) + +type Button byte + +const ( + ButtonIndexAny = 0 + ButtonIndex1 = 1 + ButtonIndex2 = 2 + ButtonIndex3 = 3 + ButtonIndex4 = 4 + ButtonIndex5 = 5 +) + +const ( + ButtonMask1 = 256 + ButtonMask2 = 512 + ButtonMask3 = 1024 + ButtonMask4 = 2048 + ButtonMask5 = 4096 + ButtonMaskAny = 32768 +) + +// ButtonPress is the event number for a ButtonPressEvent. +const ButtonPress = 4 + +type ButtonPressEvent struct { + Sequence uint16 + Detail Button + Time Timestamp + Root Window + Event Window + Child Window + RootX int16 + RootY int16 + EventX int16 + EventY int16 + State uint16 + SameScreen bool + // padding: 1 bytes +} + +// ButtonPressEventNew constructs a ButtonPressEvent value that implements xgb.Event from a byte slice. +func ButtonPressEventNew(buf []byte) xgb.Event { + v := ButtonPressEvent{} + b := 1 // don't read event number + + v.Detail = Button(buf[b]) + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Time = Timestamp(xgb.Get32(buf[b:])) + b += 4 + + v.Root = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Child = Window(xgb.Get32(buf[b:])) + b += 4 + + v.RootX = int16(xgb.Get16(buf[b:])) + b += 2 + + v.RootY = int16(xgb.Get16(buf[b:])) + b += 2 + + v.EventX = int16(xgb.Get16(buf[b:])) + b += 2 + + v.EventY = int16(xgb.Get16(buf[b:])) + b += 2 + + v.State = xgb.Get16(buf[b:]) + b += 2 + + if buf[b] == 1 { + v.SameScreen = true + } else { + v.SameScreen = false + } + b += 1 + + b += 1 // padding + + return v +} + +// Bytes writes a ButtonPressEvent value to a byte slice. +func (v ButtonPressEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 4 + b += 1 + + buf[b] = byte(v.Detail) + b += 1 + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Time)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Root)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Child)) + b += 4 + + xgb.Put16(buf[b:], uint16(v.RootX)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.RootY)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.EventX)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.EventY)) + b += 2 + + xgb.Put16(buf[b:], v.State) + b += 2 + + if v.SameScreen { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + b += 1 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the ButtonPress event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v ButtonPressEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of ButtonPressEvent. +func (v ButtonPressEvent) String() string { + fieldVals := make([]string, 0, 12) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Detail: %d", v.Detail)) + fieldVals = append(fieldVals, xgb.Sprintf("Time: %d", v.Time)) + fieldVals = append(fieldVals, xgb.Sprintf("Root: %d", v.Root)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Child: %d", v.Child)) + fieldVals = append(fieldVals, xgb.Sprintf("RootX: %d", v.RootX)) + fieldVals = append(fieldVals, xgb.Sprintf("RootY: %d", v.RootY)) + fieldVals = append(fieldVals, xgb.Sprintf("EventX: %d", v.EventX)) + fieldVals = append(fieldVals, xgb.Sprintf("EventY: %d", v.EventY)) + fieldVals = append(fieldVals, xgb.Sprintf("State: %d", v.State)) + fieldVals = append(fieldVals, xgb.Sprintf("SameScreen: %t", v.SameScreen)) + return "ButtonPress {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[4] = ButtonPressEventNew +} + +// ButtonRelease is the event number for a ButtonReleaseEvent. +const ButtonRelease = 5 + +type ButtonReleaseEvent ButtonPressEvent + +// ButtonReleaseEventNew constructs a ButtonReleaseEvent value that implements xgb.Event from a byte slice. +func ButtonReleaseEventNew(buf []byte) xgb.Event { + return ButtonReleaseEvent(ButtonPressEventNew(buf).(ButtonPressEvent)) +} + +// Bytes writes a ButtonReleaseEvent value to a byte slice. +func (v ButtonReleaseEvent) Bytes() []byte { + return ButtonPressEvent(v).Bytes() +} + +// SequenceId returns the sequence id attached to the ButtonRelease event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v ButtonReleaseEvent) SequenceId() uint16 { + return v.Sequence +} + +func (v ButtonReleaseEvent) String() string { + fieldVals := make([]string, 0, 12) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Detail: %d", v.Detail)) + fieldVals = append(fieldVals, xgb.Sprintf("Time: %d", v.Time)) + fieldVals = append(fieldVals, xgb.Sprintf("Root: %d", v.Root)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Child: %d", v.Child)) + fieldVals = append(fieldVals, xgb.Sprintf("RootX: %d", v.RootX)) + fieldVals = append(fieldVals, xgb.Sprintf("RootY: %d", v.RootY)) + fieldVals = append(fieldVals, xgb.Sprintf("EventX: %d", v.EventX)) + fieldVals = append(fieldVals, xgb.Sprintf("EventY: %d", v.EventY)) + fieldVals = append(fieldVals, xgb.Sprintf("State: %d", v.State)) + fieldVals = append(fieldVals, xgb.Sprintf("SameScreen: %t", v.SameScreen)) + return "ButtonRelease {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[5] = ButtonReleaseEventNew +} + +const ( + CapStyleNotLast = 0 + CapStyleButt = 1 + CapStyleRound = 2 + CapStyleProjecting = 3 +) + +type Char2b struct { + Byte1 byte + Byte2 byte +} + +// Char2bRead reads a byte slice into a Char2b value. +func Char2bRead(buf []byte, v *Char2b) int { + b := 0 + + v.Byte1 = buf[b] + b += 1 + + v.Byte2 = buf[b] + b += 1 + + return b +} + +// Char2bReadList reads a byte slice into a list of Char2b values. +func Char2bReadList(buf []byte, dest []Char2b) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Char2b{} + b += Char2bRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Char2b value to a byte slice. +func (v Char2b) Bytes() []byte { + buf := make([]byte, 2) + b := 0 + + buf[b] = v.Byte1 + b += 1 + + buf[b] = v.Byte2 + b += 1 + + return buf[:b] +} + +// Char2bListBytes writes a list of Char2b values to a byte slice. +func Char2bListBytes(buf []byte, list []Char2b) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +type Charinfo struct { + LeftSideBearing int16 + RightSideBearing int16 + CharacterWidth int16 + Ascent int16 + Descent int16 + Attributes uint16 +} + +// CharinfoRead reads a byte slice into a Charinfo value. +func CharinfoRead(buf []byte, v *Charinfo) int { + b := 0 + + v.LeftSideBearing = int16(xgb.Get16(buf[b:])) + b += 2 + + v.RightSideBearing = int16(xgb.Get16(buf[b:])) + b += 2 + + v.CharacterWidth = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Ascent = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Descent = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Attributes = xgb.Get16(buf[b:]) + b += 2 + + return b +} + +// CharinfoReadList reads a byte slice into a list of Charinfo values. +func CharinfoReadList(buf []byte, dest []Charinfo) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Charinfo{} + b += CharinfoRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Charinfo value to a byte slice. +func (v Charinfo) Bytes() []byte { + buf := make([]byte, 12) + b := 0 + + xgb.Put16(buf[b:], uint16(v.LeftSideBearing)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.RightSideBearing)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.CharacterWidth)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Ascent)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Descent)) + b += 2 + + xgb.Put16(buf[b:], v.Attributes) + b += 2 + + return buf[:b] +} + +// CharinfoListBytes writes a list of Charinfo values to a byte slice. +func CharinfoListBytes(buf []byte, list []Charinfo) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +const ( + CirculateRaiseLowest = 0 + CirculateLowerHighest = 1 +) + +// CirculateNotify is the event number for a CirculateNotifyEvent. +const CirculateNotify = 26 + +type CirculateNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Event Window + Window Window + // padding: 4 bytes + Place byte + // padding: 3 bytes +} + +// CirculateNotifyEventNew constructs a CirculateNotifyEvent value that implements xgb.Event from a byte slice. +func CirculateNotifyEventNew(buf []byte) xgb.Event { + v := CirculateNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + b += 4 // padding + + v.Place = buf[b] + b += 1 + + b += 3 // padding + + return v +} + +// Bytes writes a CirculateNotifyEvent value to a byte slice. +func (v CirculateNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 26 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + b += 4 // padding + + buf[b] = v.Place + b += 1 + + b += 3 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the CirculateNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v CirculateNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of CirculateNotifyEvent. +func (v CirculateNotifyEvent) String() string { + fieldVals := make([]string, 0, 6) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("Place: %d", v.Place)) + return "CirculateNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[26] = CirculateNotifyEventNew +} + +// CirculateRequest is the event number for a CirculateRequestEvent. +const CirculateRequest = 27 + +type CirculateRequestEvent CirculateNotifyEvent + +// CirculateRequestEventNew constructs a CirculateRequestEvent value that implements xgb.Event from a byte slice. +func CirculateRequestEventNew(buf []byte) xgb.Event { + return CirculateRequestEvent(CirculateNotifyEventNew(buf).(CirculateNotifyEvent)) +} + +// Bytes writes a CirculateRequestEvent value to a byte slice. +func (v CirculateRequestEvent) Bytes() []byte { + return CirculateNotifyEvent(v).Bytes() +} + +// SequenceId returns the sequence id attached to the CirculateRequest event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v CirculateRequestEvent) SequenceId() uint16 { + return v.Sequence +} + +func (v CirculateRequestEvent) String() string { + fieldVals := make([]string, 0, 6) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("Place: %d", v.Place)) + return "CirculateRequest {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[27] = CirculateRequestEventNew +} + +// ClientMessage is the event number for a ClientMessageEvent. +const ClientMessage = 33 + +type ClientMessageEvent struct { + Sequence uint16 + Format byte + Window Window + Type Atom + Data ClientMessageDataUnion +} + +// ClientMessageEventNew constructs a ClientMessageEvent value that implements xgb.Event from a byte slice. +func ClientMessageEventNew(buf []byte) xgb.Event { + v := ClientMessageEvent{} + b := 1 // don't read event number + + v.Format = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Type = Atom(xgb.Get32(buf[b:])) + b += 4 + + v.Data = ClientMessageDataUnion{} + b += ClientMessageDataUnionRead(buf[b:], &v.Data) + + return v +} + +// Bytes writes a ClientMessageEvent value to a byte slice. +func (v ClientMessageEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 33 + b += 1 + + buf[b] = v.Format + b += 1 + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Type)) + b += 4 + + { + unionBytes := v.Data.Bytes() + copy(buf[b:], unionBytes) + b += len(unionBytes) + } + + return buf +} + +// SequenceId returns the sequence id attached to the ClientMessage event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v ClientMessageEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of ClientMessageEvent. +func (v ClientMessageEvent) String() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Format: %d", v.Format)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("Type: %d", v.Type)) + return "ClientMessage {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[33] = ClientMessageEventNew +} + +// ClientMessageDataUnion is a represention of the ClientMessageDataUnion union type. +// Note that to *create* a Union, you should *never* create +// this struct directly (unless you know what you're doing). +// Instead use one of the following constructors for 'ClientMessageDataUnion': +// ClientMessageDataUnionData8New(Data8 []byte) ClientMessageDataUnion +// ClientMessageDataUnionData16New(Data16 []uint16) ClientMessageDataUnion +// ClientMessageDataUnionData32New(Data32 []uint32) ClientMessageDataUnion +type ClientMessageDataUnion struct { + Data8 []byte // size: 20 + Data16 []uint16 // size: 20 + Data32 []uint32 // size: 20 +} + +// ClientMessageDataUnionData8New constructs a new ClientMessageDataUnion union type with the Data8 field. +func ClientMessageDataUnionData8New(Data8 []byte) ClientMessageDataUnion { + var b int + buf := make([]byte, 20) + + copy(buf[b:], Data8[:20]) + b += int(20) + + // Create the Union type + v := ClientMessageDataUnion{} + + // Now copy buf into all fields + + b = 0 // always read the same bytes + v.Data8 = make([]byte, 20) + copy(v.Data8[:20], buf[b:]) + b += int(20) + + b = 0 // always read the same bytes + v.Data16 = make([]uint16, 10) + for i := 0; i < int(10); i++ { + v.Data16[i] = xgb.Get16(buf[b:]) + b += 2 + } + + b = 0 // always read the same bytes + v.Data32 = make([]uint32, 5) + for i := 0; i < int(5); i++ { + v.Data32[i] = xgb.Get32(buf[b:]) + b += 4 + } + + return v +} + +// ClientMessageDataUnionData16New constructs a new ClientMessageDataUnion union type with the Data16 field. +func ClientMessageDataUnionData16New(Data16 []uint16) ClientMessageDataUnion { + var b int + buf := make([]byte, 20) + + for i := 0; i < int(10); i++ { + xgb.Put16(buf[b:], Data16[i]) + b += 2 + } + + // Create the Union type + v := ClientMessageDataUnion{} + + // Now copy buf into all fields + + b = 0 // always read the same bytes + v.Data8 = make([]byte, 20) + copy(v.Data8[:20], buf[b:]) + b += int(20) + + b = 0 // always read the same bytes + v.Data16 = make([]uint16, 10) + for i := 0; i < int(10); i++ { + v.Data16[i] = xgb.Get16(buf[b:]) + b += 2 + } + + b = 0 // always read the same bytes + v.Data32 = make([]uint32, 5) + for i := 0; i < int(5); i++ { + v.Data32[i] = xgb.Get32(buf[b:]) + b += 4 + } + + return v +} + +// ClientMessageDataUnionData32New constructs a new ClientMessageDataUnion union type with the Data32 field. +func ClientMessageDataUnionData32New(Data32 []uint32) ClientMessageDataUnion { + var b int + buf := make([]byte, 20) + + for i := 0; i < int(5); i++ { + xgb.Put32(buf[b:], Data32[i]) + b += 4 + } + + // Create the Union type + v := ClientMessageDataUnion{} + + // Now copy buf into all fields + + b = 0 // always read the same bytes + v.Data8 = make([]byte, 20) + copy(v.Data8[:20], buf[b:]) + b += int(20) + + b = 0 // always read the same bytes + v.Data16 = make([]uint16, 10) + for i := 0; i < int(10); i++ { + v.Data16[i] = xgb.Get16(buf[b:]) + b += 2 + } + + b = 0 // always read the same bytes + v.Data32 = make([]uint32, 5) + for i := 0; i < int(5); i++ { + v.Data32[i] = xgb.Get32(buf[b:]) + b += 4 + } + + return v +} + +// ClientMessageDataUnionRead reads a byte slice into a ClientMessageDataUnion value. +func ClientMessageDataUnionRead(buf []byte, v *ClientMessageDataUnion) int { + var b int + + b = 0 // re-read the same bytes + v.Data8 = make([]byte, 20) + copy(v.Data8[:20], buf[b:]) + b += int(20) + + b = 0 // re-read the same bytes + v.Data16 = make([]uint16, 10) + for i := 0; i < int(10); i++ { + v.Data16[i] = xgb.Get16(buf[b:]) + b += 2 + } + + b = 0 // re-read the same bytes + v.Data32 = make([]uint32, 5) + for i := 0; i < int(5); i++ { + v.Data32[i] = xgb.Get32(buf[b:]) + b += 4 + } + + return 20 +} + +// ClientMessageDataUnionReadList reads a byte slice into a list of ClientMessageDataUnion values. +func ClientMessageDataUnionReadList(buf []byte, dest []ClientMessageDataUnion) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = ClientMessageDataUnion{} + b += ClientMessageDataUnionRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a ClientMessageDataUnion value to a byte slice. +// Each field in a union must contain the same data. +// So simply pick the first field and write that to the wire. +func (v ClientMessageDataUnion) Bytes() []byte { + buf := make([]byte, 20) + b := 0 + + copy(buf[b:], v.Data8[:20]) + b += int(20) + return buf +} + +// ClientMessageDataUnionListBytes writes a list of ClientMessageDataUnion values to a byte slice. +func ClientMessageDataUnionListBytes(buf []byte, list []ClientMessageDataUnion) int { + b := 0 + var unionBytes []byte + for _, item := range list { + unionBytes = item.Bytes() + copy(buf[b:], unionBytes) + b += xgb.Pad(len(unionBytes)) + } + return b +} + +const ( + ClipOrderingUnsorted = 0 + ClipOrderingYSorted = 1 + ClipOrderingYXSorted = 2 + ClipOrderingYXBanded = 3 +) + +const ( + CloseDownDestroyAll = 0 + CloseDownRetainPermanent = 1 + CloseDownRetainTemporary = 2 +) + +const ( + ColorFlagRed = 1 + ColorFlagGreen = 2 + ColorFlagBlue = 4 +) + +type Coloritem struct { + Pixel uint32 + Red uint16 + Green uint16 + Blue uint16 + Flags byte + // padding: 1 bytes +} + +// ColoritemRead reads a byte slice into a Coloritem value. +func ColoritemRead(buf []byte, v *Coloritem) int { + b := 0 + + v.Pixel = xgb.Get32(buf[b:]) + b += 4 + + v.Red = xgb.Get16(buf[b:]) + b += 2 + + v.Green = xgb.Get16(buf[b:]) + b += 2 + + v.Blue = xgb.Get16(buf[b:]) + b += 2 + + v.Flags = buf[b] + b += 1 + + b += 1 // padding + + return b +} + +// ColoritemReadList reads a byte slice into a list of Coloritem values. +func ColoritemReadList(buf []byte, dest []Coloritem) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Coloritem{} + b += ColoritemRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Coloritem value to a byte slice. +func (v Coloritem) Bytes() []byte { + buf := make([]byte, 12) + b := 0 + + xgb.Put32(buf[b:], v.Pixel) + b += 4 + + xgb.Put16(buf[b:], v.Red) + b += 2 + + xgb.Put16(buf[b:], v.Green) + b += 2 + + xgb.Put16(buf[b:], v.Blue) + b += 2 + + buf[b] = v.Flags + b += 1 + + b += 1 // padding + + return buf[:b] +} + +// ColoritemListBytes writes a list of Coloritem values to a byte slice. +func ColoritemListBytes(buf []byte, list []Coloritem) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +type Colormap uint32 + +func NewColormapId(c *xgb.Conn) (Colormap, error) { + id, err := c.NewId() + if err != nil { + return 0, err + } + return Colormap(id), nil +} + +// BadColormap is the error number for a BadColormap. +const BadColormap = 12 + +type ColormapError ValueError + +// ColormapErrorNew constructs a ColormapError value that implements xgb.Error from a byte slice. +func ColormapErrorNew(buf []byte) xgb.Error { + v := ColormapError(ValueErrorNew(buf).(ValueError)) + v.NiceName = "Colormap" + return v +} + +// SequenceId returns the sequence id attached to the BadColormap error. +// This is mostly used internally. +func (err ColormapError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadColormap error. If no bad value exists, 0 is returned. +func (err ColormapError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadColormap error. +func (err ColormapError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadColormap {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[12] = ColormapErrorNew +} + +const ( + ColormapNone = 0 +) + +const ( + ColormapAllocNone = 0 + ColormapAllocAll = 1 +) + +// ColormapNotify is the event number for a ColormapNotifyEvent. +const ColormapNotify = 32 + +type ColormapNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Window Window + Colormap Colormap + New bool + State byte + // padding: 2 bytes +} + +// ColormapNotifyEventNew constructs a ColormapNotifyEvent value that implements xgb.Event from a byte slice. +func ColormapNotifyEventNew(buf []byte) xgb.Event { + v := ColormapNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Colormap = Colormap(xgb.Get32(buf[b:])) + b += 4 + + if buf[b] == 1 { + v.New = true + } else { + v.New = false + } + b += 1 + + v.State = buf[b] + b += 1 + + b += 2 // padding + + return v +} + +// Bytes writes a ColormapNotifyEvent value to a byte slice. +func (v ColormapNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 32 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Colormap)) + b += 4 + + if v.New { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + buf[b] = v.State + b += 1 + + b += 2 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the ColormapNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v ColormapNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of ColormapNotifyEvent. +func (v ColormapNotifyEvent) String() string { + fieldVals := make([]string, 0, 6) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("Colormap: %d", v.Colormap)) + fieldVals = append(fieldVals, xgb.Sprintf("New: %t", v.New)) + fieldVals = append(fieldVals, xgb.Sprintf("State: %d", v.State)) + return "ColormapNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[32] = ColormapNotifyEventNew +} + +const ( + ColormapStateUninstalled = 0 + ColormapStateInstalled = 1 +) + +const ( + ConfigWindowX = 1 + ConfigWindowY = 2 + ConfigWindowWidth = 4 + ConfigWindowHeight = 8 + ConfigWindowBorderWidth = 16 + ConfigWindowSibling = 32 + ConfigWindowStackMode = 64 +) + +// ConfigureNotify is the event number for a ConfigureNotifyEvent. +const ConfigureNotify = 22 + +type ConfigureNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Event Window + Window Window + AboveSibling Window + X int16 + Y int16 + Width uint16 + Height uint16 + BorderWidth uint16 + OverrideRedirect bool + // padding: 1 bytes +} + +// ConfigureNotifyEventNew constructs a ConfigureNotifyEvent value that implements xgb.Event from a byte slice. +func ConfigureNotifyEventNew(buf []byte) xgb.Event { + v := ConfigureNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + v.AboveSibling = Window(xgb.Get32(buf[b:])) + b += 4 + + v.X = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Width = xgb.Get16(buf[b:]) + b += 2 + + v.Height = xgb.Get16(buf[b:]) + b += 2 + + v.BorderWidth = xgb.Get16(buf[b:]) + b += 2 + + if buf[b] == 1 { + v.OverrideRedirect = true + } else { + v.OverrideRedirect = false + } + b += 1 + + b += 1 // padding + + return v +} + +// Bytes writes a ConfigureNotifyEvent value to a byte slice. +func (v ConfigureNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 22 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.AboveSibling)) + b += 4 + + xgb.Put16(buf[b:], uint16(v.X)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Y)) + b += 2 + + xgb.Put16(buf[b:], v.Width) + b += 2 + + xgb.Put16(buf[b:], v.Height) + b += 2 + + xgb.Put16(buf[b:], v.BorderWidth) + b += 2 + + if v.OverrideRedirect { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + b += 1 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the ConfigureNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v ConfigureNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of ConfigureNotifyEvent. +func (v ConfigureNotifyEvent) String() string { + fieldVals := make([]string, 0, 11) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("AboveSibling: %d", v.AboveSibling)) + fieldVals = append(fieldVals, xgb.Sprintf("X: %d", v.X)) + fieldVals = append(fieldVals, xgb.Sprintf("Y: %d", v.Y)) + fieldVals = append(fieldVals, xgb.Sprintf("Width: %d", v.Width)) + fieldVals = append(fieldVals, xgb.Sprintf("Height: %d", v.Height)) + fieldVals = append(fieldVals, xgb.Sprintf("BorderWidth: %d", v.BorderWidth)) + fieldVals = append(fieldVals, xgb.Sprintf("OverrideRedirect: %t", v.OverrideRedirect)) + return "ConfigureNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[22] = ConfigureNotifyEventNew +} + +// ConfigureRequest is the event number for a ConfigureRequestEvent. +const ConfigureRequest = 23 + +type ConfigureRequestEvent struct { + Sequence uint16 + StackMode byte + Parent Window + Window Window + Sibling Window + X int16 + Y int16 + Width uint16 + Height uint16 + BorderWidth uint16 + ValueMask uint16 +} + +// ConfigureRequestEventNew constructs a ConfigureRequestEvent value that implements xgb.Event from a byte slice. +func ConfigureRequestEventNew(buf []byte) xgb.Event { + v := ConfigureRequestEvent{} + b := 1 // don't read event number + + v.StackMode = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Parent = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Sibling = Window(xgb.Get32(buf[b:])) + b += 4 + + v.X = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Width = xgb.Get16(buf[b:]) + b += 2 + + v.Height = xgb.Get16(buf[b:]) + b += 2 + + v.BorderWidth = xgb.Get16(buf[b:]) + b += 2 + + v.ValueMask = xgb.Get16(buf[b:]) + b += 2 + + return v +} + +// Bytes writes a ConfigureRequestEvent value to a byte slice. +func (v ConfigureRequestEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 23 + b += 1 + + buf[b] = v.StackMode + b += 1 + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Parent)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Sibling)) + b += 4 + + xgb.Put16(buf[b:], uint16(v.X)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Y)) + b += 2 + + xgb.Put16(buf[b:], v.Width) + b += 2 + + xgb.Put16(buf[b:], v.Height) + b += 2 + + xgb.Put16(buf[b:], v.BorderWidth) + b += 2 + + xgb.Put16(buf[b:], v.ValueMask) + b += 2 + + return buf +} + +// SequenceId returns the sequence id attached to the ConfigureRequest event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v ConfigureRequestEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of ConfigureRequestEvent. +func (v ConfigureRequestEvent) String() string { + fieldVals := make([]string, 0, 10) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("StackMode: %d", v.StackMode)) + fieldVals = append(fieldVals, xgb.Sprintf("Parent: %d", v.Parent)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("Sibling: %d", v.Sibling)) + fieldVals = append(fieldVals, xgb.Sprintf("X: %d", v.X)) + fieldVals = append(fieldVals, xgb.Sprintf("Y: %d", v.Y)) + fieldVals = append(fieldVals, xgb.Sprintf("Width: %d", v.Width)) + fieldVals = append(fieldVals, xgb.Sprintf("Height: %d", v.Height)) + fieldVals = append(fieldVals, xgb.Sprintf("BorderWidth: %d", v.BorderWidth)) + fieldVals = append(fieldVals, xgb.Sprintf("ValueMask: %d", v.ValueMask)) + return "ConfigureRequest {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[23] = ConfigureRequestEventNew +} + +const ( + CoordModeOrigin = 0 + CoordModePrevious = 1 +) + +// CreateNotify is the event number for a CreateNotifyEvent. +const CreateNotify = 16 + +type CreateNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Parent Window + Window Window + X int16 + Y int16 + Width uint16 + Height uint16 + BorderWidth uint16 + OverrideRedirect bool + // padding: 1 bytes +} + +// CreateNotifyEventNew constructs a CreateNotifyEvent value that implements xgb.Event from a byte slice. +func CreateNotifyEventNew(buf []byte) xgb.Event { + v := CreateNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Parent = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + v.X = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Width = xgb.Get16(buf[b:]) + b += 2 + + v.Height = xgb.Get16(buf[b:]) + b += 2 + + v.BorderWidth = xgb.Get16(buf[b:]) + b += 2 + + if buf[b] == 1 { + v.OverrideRedirect = true + } else { + v.OverrideRedirect = false + } + b += 1 + + b += 1 // padding + + return v +} + +// Bytes writes a CreateNotifyEvent value to a byte slice. +func (v CreateNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 16 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Parent)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + xgb.Put16(buf[b:], uint16(v.X)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Y)) + b += 2 + + xgb.Put16(buf[b:], v.Width) + b += 2 + + xgb.Put16(buf[b:], v.Height) + b += 2 + + xgb.Put16(buf[b:], v.BorderWidth) + b += 2 + + if v.OverrideRedirect { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + b += 1 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the CreateNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v CreateNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of CreateNotifyEvent. +func (v CreateNotifyEvent) String() string { + fieldVals := make([]string, 0, 10) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Parent: %d", v.Parent)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("X: %d", v.X)) + fieldVals = append(fieldVals, xgb.Sprintf("Y: %d", v.Y)) + fieldVals = append(fieldVals, xgb.Sprintf("Width: %d", v.Width)) + fieldVals = append(fieldVals, xgb.Sprintf("Height: %d", v.Height)) + fieldVals = append(fieldVals, xgb.Sprintf("BorderWidth: %d", v.BorderWidth)) + fieldVals = append(fieldVals, xgb.Sprintf("OverrideRedirect: %t", v.OverrideRedirect)) + return "CreateNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[16] = CreateNotifyEventNew +} + +type Cursor uint32 + +func NewCursorId(c *xgb.Conn) (Cursor, error) { + id, err := c.NewId() + if err != nil { + return 0, err + } + return Cursor(id), nil +} + +// BadCursor is the error number for a BadCursor. +const BadCursor = 6 + +type CursorError ValueError + +// CursorErrorNew constructs a CursorError value that implements xgb.Error from a byte slice. +func CursorErrorNew(buf []byte) xgb.Error { + v := CursorError(ValueErrorNew(buf).(ValueError)) + v.NiceName = "Cursor" + return v +} + +// SequenceId returns the sequence id attached to the BadCursor error. +// This is mostly used internally. +func (err CursorError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadCursor error. If no bad value exists, 0 is returned. +func (err CursorError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadCursor error. +func (err CursorError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadCursor {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[6] = CursorErrorNew +} + +const ( + CursorNone = 0 +) + +const ( + CwBackPixmap = 1 + CwBackPixel = 2 + CwBorderPixmap = 4 + CwBorderPixel = 8 + CwBitGravity = 16 + CwWinGravity = 32 + CwBackingStore = 64 + CwBackingPlanes = 128 + CwBackingPixel = 256 + CwOverrideRedirect = 512 + CwSaveUnder = 1024 + CwEventMask = 2048 + CwDontPropagate = 4096 + CwColormap = 8192 + CwCursor = 16384 +) + +type DepthInfo struct { + Depth byte + // padding: 1 bytes + VisualsLen uint16 + // padding: 4 bytes + Visuals []VisualInfo // size: xgb.Pad((int(VisualsLen) * 24)) +} + +// DepthInfoRead reads a byte slice into a DepthInfo value. +func DepthInfoRead(buf []byte, v *DepthInfo) int { + b := 0 + + v.Depth = buf[b] + b += 1 + + b += 1 // padding + + v.VisualsLen = xgb.Get16(buf[b:]) + b += 2 + + b += 4 // padding + + v.Visuals = make([]VisualInfo, v.VisualsLen) + b += VisualInfoReadList(buf[b:], v.Visuals) + + return b +} + +// DepthInfoReadList reads a byte slice into a list of DepthInfo values. +func DepthInfoReadList(buf []byte, dest []DepthInfo) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = DepthInfo{} + b += DepthInfoRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a DepthInfo value to a byte slice. +func (v DepthInfo) Bytes() []byte { + buf := make([]byte, (8 + xgb.Pad((int(v.VisualsLen) * 24)))) + b := 0 + + buf[b] = v.Depth + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], v.VisualsLen) + b += 2 + + b += 4 // padding + + b += VisualInfoListBytes(buf[b:], v.Visuals) + + return buf[:b] +} + +// DepthInfoListBytes writes a list of DepthInfo values to a byte slice. +func DepthInfoListBytes(buf []byte, list []DepthInfo) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// DepthInfoListSize computes the size (bytes) of a list of DepthInfo values. +func DepthInfoListSize(list []DepthInfo) int { + size := 0 + for _, item := range list { + size += (8 + xgb.Pad((int(item.VisualsLen) * 24))) + } + return size +} + +// DestroyNotify is the event number for a DestroyNotifyEvent. +const DestroyNotify = 17 + +type DestroyNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Event Window + Window Window +} + +// DestroyNotifyEventNew constructs a DestroyNotifyEvent value that implements xgb.Event from a byte slice. +func DestroyNotifyEventNew(buf []byte) xgb.Event { + v := DestroyNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + return v +} + +// Bytes writes a DestroyNotifyEvent value to a byte slice. +func (v DestroyNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 17 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + return buf +} + +// SequenceId returns the sequence id attached to the DestroyNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v DestroyNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of DestroyNotifyEvent. +func (v DestroyNotifyEvent) String() string { + fieldVals := make([]string, 0, 3) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + return "DestroyNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[17] = DestroyNotifyEventNew +} + +type Drawable uint32 + +func NewDrawableId(c *xgb.Conn) (Drawable, error) { + id, err := c.NewId() + if err != nil { + return 0, err + } + return Drawable(id), nil +} + +// BadDrawable is the error number for a BadDrawable. +const BadDrawable = 9 + +type DrawableError ValueError + +// DrawableErrorNew constructs a DrawableError value that implements xgb.Error from a byte slice. +func DrawableErrorNew(buf []byte) xgb.Error { + v := DrawableError(ValueErrorNew(buf).(ValueError)) + v.NiceName = "Drawable" + return v +} + +// SequenceId returns the sequence id attached to the BadDrawable error. +// This is mostly used internally. +func (err DrawableError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadDrawable error. If no bad value exists, 0 is returned. +func (err DrawableError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadDrawable error. +func (err DrawableError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadDrawable {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[9] = DrawableErrorNew +} + +// EnterNotify is the event number for a EnterNotifyEvent. +const EnterNotify = 7 + +type EnterNotifyEvent struct { + Sequence uint16 + Detail byte + Time Timestamp + Root Window + Event Window + Child Window + RootX int16 + RootY int16 + EventX int16 + EventY int16 + State uint16 + Mode byte + SameScreenFocus byte +} + +// EnterNotifyEventNew constructs a EnterNotifyEvent value that implements xgb.Event from a byte slice. +func EnterNotifyEventNew(buf []byte) xgb.Event { + v := EnterNotifyEvent{} + b := 1 // don't read event number + + v.Detail = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Time = Timestamp(xgb.Get32(buf[b:])) + b += 4 + + v.Root = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Child = Window(xgb.Get32(buf[b:])) + b += 4 + + v.RootX = int16(xgb.Get16(buf[b:])) + b += 2 + + v.RootY = int16(xgb.Get16(buf[b:])) + b += 2 + + v.EventX = int16(xgb.Get16(buf[b:])) + b += 2 + + v.EventY = int16(xgb.Get16(buf[b:])) + b += 2 + + v.State = xgb.Get16(buf[b:]) + b += 2 + + v.Mode = buf[b] + b += 1 + + v.SameScreenFocus = buf[b] + b += 1 + + return v +} + +// Bytes writes a EnterNotifyEvent value to a byte slice. +func (v EnterNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 7 + b += 1 + + buf[b] = v.Detail + b += 1 + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Time)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Root)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Child)) + b += 4 + + xgb.Put16(buf[b:], uint16(v.RootX)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.RootY)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.EventX)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.EventY)) + b += 2 + + xgb.Put16(buf[b:], v.State) + b += 2 + + buf[b] = v.Mode + b += 1 + + buf[b] = v.SameScreenFocus + b += 1 + + return buf +} + +// SequenceId returns the sequence id attached to the EnterNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v EnterNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of EnterNotifyEvent. +func (v EnterNotifyEvent) String() string { + fieldVals := make([]string, 0, 12) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Detail: %d", v.Detail)) + fieldVals = append(fieldVals, xgb.Sprintf("Time: %d", v.Time)) + fieldVals = append(fieldVals, xgb.Sprintf("Root: %d", v.Root)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Child: %d", v.Child)) + fieldVals = append(fieldVals, xgb.Sprintf("RootX: %d", v.RootX)) + fieldVals = append(fieldVals, xgb.Sprintf("RootY: %d", v.RootY)) + fieldVals = append(fieldVals, xgb.Sprintf("EventX: %d", v.EventX)) + fieldVals = append(fieldVals, xgb.Sprintf("EventY: %d", v.EventY)) + fieldVals = append(fieldVals, xgb.Sprintf("State: %d", v.State)) + fieldVals = append(fieldVals, xgb.Sprintf("Mode: %d", v.Mode)) + fieldVals = append(fieldVals, xgb.Sprintf("SameScreenFocus: %d", v.SameScreenFocus)) + return "EnterNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[7] = EnterNotifyEventNew +} + +const ( + EventMaskNoEvent = 0 + EventMaskKeyPress = 1 + EventMaskKeyRelease = 2 + EventMaskButtonPress = 4 + EventMaskButtonRelease = 8 + EventMaskEnterWindow = 16 + EventMaskLeaveWindow = 32 + EventMaskPointerMotion = 64 + EventMaskPointerMotionHint = 128 + EventMaskButton1Motion = 256 + EventMaskButton2Motion = 512 + EventMaskButton3Motion = 1024 + EventMaskButton4Motion = 2048 + EventMaskButton5Motion = 4096 + EventMaskButtonMotion = 8192 + EventMaskKeymapState = 16384 + EventMaskExposure = 32768 + EventMaskVisibilityChange = 65536 + EventMaskStructureNotify = 131072 + EventMaskResizeRedirect = 262144 + EventMaskSubstructureNotify = 524288 + EventMaskSubstructureRedirect = 1048576 + EventMaskFocusChange = 2097152 + EventMaskPropertyChange = 4194304 + EventMaskColorMapChange = 8388608 + EventMaskOwnerGrabButton = 16777216 +) + +// Expose is the event number for a ExposeEvent. +const Expose = 12 + +type ExposeEvent struct { + Sequence uint16 + // padding: 1 bytes + Window Window + X uint16 + Y uint16 + Width uint16 + Height uint16 + Count uint16 + // padding: 2 bytes +} + +// ExposeEventNew constructs a ExposeEvent value that implements xgb.Event from a byte slice. +func ExposeEventNew(buf []byte) xgb.Event { + v := ExposeEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + v.X = xgb.Get16(buf[b:]) + b += 2 + + v.Y = xgb.Get16(buf[b:]) + b += 2 + + v.Width = xgb.Get16(buf[b:]) + b += 2 + + v.Height = xgb.Get16(buf[b:]) + b += 2 + + v.Count = xgb.Get16(buf[b:]) + b += 2 + + b += 2 // padding + + return v +} + +// Bytes writes a ExposeEvent value to a byte slice. +func (v ExposeEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 12 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + xgb.Put16(buf[b:], v.X) + b += 2 + + xgb.Put16(buf[b:], v.Y) + b += 2 + + xgb.Put16(buf[b:], v.Width) + b += 2 + + xgb.Put16(buf[b:], v.Height) + b += 2 + + xgb.Put16(buf[b:], v.Count) + b += 2 + + b += 2 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the Expose event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v ExposeEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of ExposeEvent. +func (v ExposeEvent) String() string { + fieldVals := make([]string, 0, 8) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("X: %d", v.X)) + fieldVals = append(fieldVals, xgb.Sprintf("Y: %d", v.Y)) + fieldVals = append(fieldVals, xgb.Sprintf("Width: %d", v.Width)) + fieldVals = append(fieldVals, xgb.Sprintf("Height: %d", v.Height)) + fieldVals = append(fieldVals, xgb.Sprintf("Count: %d", v.Count)) + return "Expose {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[12] = ExposeEventNew +} + +const ( + ExposuresNotAllowed = 0 + ExposuresAllowed = 1 + ExposuresDefault = 2 +) + +const ( + FamilyInternet = 0 + FamilyDECnet = 1 + FamilyChaos = 2 + FamilyServerInterpreted = 5 + FamilyInternet6 = 6 +) + +const ( + FillRuleEvenOdd = 0 + FillRuleWinding = 1 +) + +const ( + FillStyleSolid = 0 + FillStyleTiled = 1 + FillStyleStippled = 2 + FillStyleOpaqueStippled = 3 +) + +// FocusIn is the event number for a FocusInEvent. +const FocusIn = 9 + +type FocusInEvent struct { + Sequence uint16 + Detail byte + Event Window + Mode byte + // padding: 3 bytes +} + +// FocusInEventNew constructs a FocusInEvent value that implements xgb.Event from a byte slice. +func FocusInEventNew(buf []byte) xgb.Event { + v := FocusInEvent{} + b := 1 // don't read event number + + v.Detail = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Mode = buf[b] + b += 1 + + b += 3 // padding + + return v +} + +// Bytes writes a FocusInEvent value to a byte slice. +func (v FocusInEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 9 + b += 1 + + buf[b] = v.Detail + b += 1 + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + buf[b] = v.Mode + b += 1 + + b += 3 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the FocusIn event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v FocusInEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of FocusInEvent. +func (v FocusInEvent) String() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Detail: %d", v.Detail)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Mode: %d", v.Mode)) + return "FocusIn {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[9] = FocusInEventNew +} + +// FocusOut is the event number for a FocusOutEvent. +const FocusOut = 10 + +type FocusOutEvent FocusInEvent + +// FocusOutEventNew constructs a FocusOutEvent value that implements xgb.Event from a byte slice. +func FocusOutEventNew(buf []byte) xgb.Event { + return FocusOutEvent(FocusInEventNew(buf).(FocusInEvent)) +} + +// Bytes writes a FocusOutEvent value to a byte slice. +func (v FocusOutEvent) Bytes() []byte { + return FocusInEvent(v).Bytes() +} + +// SequenceId returns the sequence id attached to the FocusOut event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v FocusOutEvent) SequenceId() uint16 { + return v.Sequence +} + +func (v FocusOutEvent) String() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Detail: %d", v.Detail)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Mode: %d", v.Mode)) + return "FocusOut {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[10] = FocusOutEventNew +} + +type Font uint32 + +func NewFontId(c *xgb.Conn) (Font, error) { + id, err := c.NewId() + if err != nil { + return 0, err + } + return Font(id), nil +} + +// BadFont is the error number for a BadFont. +const BadFont = 7 + +type FontError ValueError + +// FontErrorNew constructs a FontError value that implements xgb.Error from a byte slice. +func FontErrorNew(buf []byte) xgb.Error { + v := FontError(ValueErrorNew(buf).(ValueError)) + v.NiceName = "Font" + return v +} + +// SequenceId returns the sequence id attached to the BadFont error. +// This is mostly used internally. +func (err FontError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadFont error. If no bad value exists, 0 is returned. +func (err FontError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadFont error. +func (err FontError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadFont {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[7] = FontErrorNew +} + +const ( + FontNone = 0 +) + +const ( + FontDrawLeftToRight = 0 + FontDrawRightToLeft = 1 +) + +type Fontable uint32 + +func NewFontableId(c *xgb.Conn) (Fontable, error) { + id, err := c.NewId() + if err != nil { + return 0, err + } + return Fontable(id), nil +} + +type Fontprop struct { + Name Atom + Value uint32 +} + +// FontpropRead reads a byte slice into a Fontprop value. +func FontpropRead(buf []byte, v *Fontprop) int { + b := 0 + + v.Name = Atom(xgb.Get32(buf[b:])) + b += 4 + + v.Value = xgb.Get32(buf[b:]) + b += 4 + + return b +} + +// FontpropReadList reads a byte slice into a list of Fontprop values. +func FontpropReadList(buf []byte, dest []Fontprop) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Fontprop{} + b += FontpropRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Fontprop value to a byte slice. +func (v Fontprop) Bytes() []byte { + buf := make([]byte, 8) + b := 0 + + xgb.Put32(buf[b:], uint32(v.Name)) + b += 4 + + xgb.Put32(buf[b:], v.Value) + b += 4 + + return buf[:b] +} + +// FontpropListBytes writes a list of Fontprop values to a byte slice. +func FontpropListBytes(buf []byte, list []Fontprop) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +type Format struct { + Depth byte + BitsPerPixel byte + ScanlinePad byte + // padding: 5 bytes +} + +// FormatRead reads a byte slice into a Format value. +func FormatRead(buf []byte, v *Format) int { + b := 0 + + v.Depth = buf[b] + b += 1 + + v.BitsPerPixel = buf[b] + b += 1 + + v.ScanlinePad = buf[b] + b += 1 + + b += 5 // padding + + return b +} + +// FormatReadList reads a byte slice into a list of Format values. +func FormatReadList(buf []byte, dest []Format) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Format{} + b += FormatRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Format value to a byte slice. +func (v Format) Bytes() []byte { + buf := make([]byte, 8) + b := 0 + + buf[b] = v.Depth + b += 1 + + buf[b] = v.BitsPerPixel + b += 1 + + buf[b] = v.ScanlinePad + b += 1 + + b += 5 // padding + + return buf[:b] +} + +// FormatListBytes writes a list of Format values to a byte slice. +func FormatListBytes(buf []byte, list []Format) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// BadGContext is the error number for a BadGContext. +const BadGContext = 13 + +type GContextError ValueError + +// GContextErrorNew constructs a GContextError value that implements xgb.Error from a byte slice. +func GContextErrorNew(buf []byte) xgb.Error { + v := GContextError(ValueErrorNew(buf).(ValueError)) + v.NiceName = "GContext" + return v +} + +// SequenceId returns the sequence id attached to the BadGContext error. +// This is mostly used internally. +func (err GContextError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadGContext error. If no bad value exists, 0 is returned. +func (err GContextError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadGContext error. +func (err GContextError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadGContext {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[13] = GContextErrorNew +} + +const ( + GcFunction = 1 + GcPlaneMask = 2 + GcForeground = 4 + GcBackground = 8 + GcLineWidth = 16 + GcLineStyle = 32 + GcCapStyle = 64 + GcJoinStyle = 128 + GcFillStyle = 256 + GcFillRule = 512 + GcTile = 1024 + GcStipple = 2048 + GcTileStippleOriginX = 4096 + GcTileStippleOriginY = 8192 + GcFont = 16384 + GcSubwindowMode = 32768 + GcGraphicsExposures = 65536 + GcClipOriginX = 131072 + GcClipOriginY = 262144 + GcClipMask = 524288 + GcDashOffset = 1048576 + GcDashList = 2097152 + GcArcMode = 4194304 +) + +type Gcontext uint32 + +func NewGcontextId(c *xgb.Conn) (Gcontext, error) { + id, err := c.NewId() + if err != nil { + return 0, err + } + return Gcontext(id), nil +} + +// GeGeneric is the event number for a GeGenericEvent. +const GeGeneric = 35 + +type GeGenericEvent struct { + Sequence uint16 + // padding: 22 bytes +} + +// GeGenericEventNew constructs a GeGenericEvent value that implements xgb.Event from a byte slice. +func GeGenericEventNew(buf []byte) xgb.Event { + v := GeGenericEvent{} + b := 1 // don't read event number + + b += 22 // padding + + return v +} + +// Bytes writes a GeGenericEvent value to a byte slice. +func (v GeGenericEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 35 + b += 1 + + b += 22 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the GeGeneric event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v GeGenericEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of GeGenericEvent. +func (v GeGenericEvent) String() string { + fieldVals := make([]string, 0, 1) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + return "GeGeneric {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[35] = GeGenericEventNew +} + +const ( + GetPropertyTypeAny = 0 +) + +const ( + GrabAny = 0 +) + +const ( + GrabModeSync = 0 + GrabModeAsync = 1 +) + +const ( + GrabStatusSuccess = 0 + GrabStatusAlreadyGrabbed = 1 + GrabStatusInvalidTime = 2 + GrabStatusNotViewable = 3 + GrabStatusFrozen = 4 +) + +// GraphicsExposure is the event number for a GraphicsExposureEvent. +const GraphicsExposure = 13 + +type GraphicsExposureEvent struct { + Sequence uint16 + // padding: 1 bytes + Drawable Drawable + X uint16 + Y uint16 + Width uint16 + Height uint16 + MinorOpcode uint16 + Count uint16 + MajorOpcode byte + // padding: 3 bytes +} + +// GraphicsExposureEventNew constructs a GraphicsExposureEvent value that implements xgb.Event from a byte slice. +func GraphicsExposureEventNew(buf []byte) xgb.Event { + v := GraphicsExposureEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Drawable = Drawable(xgb.Get32(buf[b:])) + b += 4 + + v.X = xgb.Get16(buf[b:]) + b += 2 + + v.Y = xgb.Get16(buf[b:]) + b += 2 + + v.Width = xgb.Get16(buf[b:]) + b += 2 + + v.Height = xgb.Get16(buf[b:]) + b += 2 + + v.MinorOpcode = xgb.Get16(buf[b:]) + b += 2 + + v.Count = xgb.Get16(buf[b:]) + b += 2 + + v.MajorOpcode = buf[b] + b += 1 + + b += 3 // padding + + return v +} + +// Bytes writes a GraphicsExposureEvent value to a byte slice. +func (v GraphicsExposureEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 13 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Drawable)) + b += 4 + + xgb.Put16(buf[b:], v.X) + b += 2 + + xgb.Put16(buf[b:], v.Y) + b += 2 + + xgb.Put16(buf[b:], v.Width) + b += 2 + + xgb.Put16(buf[b:], v.Height) + b += 2 + + xgb.Put16(buf[b:], v.MinorOpcode) + b += 2 + + xgb.Put16(buf[b:], v.Count) + b += 2 + + buf[b] = v.MajorOpcode + b += 1 + + b += 3 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the GraphicsExposure event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v GraphicsExposureEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of GraphicsExposureEvent. +func (v GraphicsExposureEvent) String() string { + fieldVals := make([]string, 0, 10) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Drawable: %d", v.Drawable)) + fieldVals = append(fieldVals, xgb.Sprintf("X: %d", v.X)) + fieldVals = append(fieldVals, xgb.Sprintf("Y: %d", v.Y)) + fieldVals = append(fieldVals, xgb.Sprintf("Width: %d", v.Width)) + fieldVals = append(fieldVals, xgb.Sprintf("Height: %d", v.Height)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", v.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("Count: %d", v.Count)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", v.MajorOpcode)) + return "GraphicsExposure {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[13] = GraphicsExposureEventNew +} + +const ( + GravityBitForget = 0 + GravityWinUnmap = 0 + GravityNorthWest = 1 + GravityNorth = 2 + GravityNorthEast = 3 + GravityWest = 4 + GravityCenter = 5 + GravityEast = 6 + GravitySouthWest = 7 + GravitySouth = 8 + GravitySouthEast = 9 + GravityStatic = 10 +) + +// GravityNotify is the event number for a GravityNotifyEvent. +const GravityNotify = 24 + +type GravityNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Event Window + Window Window + X int16 + Y int16 +} + +// GravityNotifyEventNew constructs a GravityNotifyEvent value that implements xgb.Event from a byte slice. +func GravityNotifyEventNew(buf []byte) xgb.Event { + v := GravityNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + v.X = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y = int16(xgb.Get16(buf[b:])) + b += 2 + + return v +} + +// Bytes writes a GravityNotifyEvent value to a byte slice. +func (v GravityNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 24 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + xgb.Put16(buf[b:], uint16(v.X)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Y)) + b += 2 + + return buf +} + +// SequenceId returns the sequence id attached to the GravityNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v GravityNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of GravityNotifyEvent. +func (v GravityNotifyEvent) String() string { + fieldVals := make([]string, 0, 5) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("X: %d", v.X)) + fieldVals = append(fieldVals, xgb.Sprintf("Y: %d", v.Y)) + return "GravityNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[24] = GravityNotifyEventNew +} + +const ( + GxClear = 0 + GxAnd = 1 + GxAndReverse = 2 + GxCopy = 3 + GxAndInverted = 4 + GxNoop = 5 + GxXor = 6 + GxOr = 7 + GxNor = 8 + GxEquiv = 9 + GxInvert = 10 + GxOrReverse = 11 + GxCopyInverted = 12 + GxOrInverted = 13 + GxNand = 14 + GxSet = 15 +) + +type Host struct { + Family byte + // padding: 1 bytes + AddressLen uint16 + Address []byte // size: xgb.Pad((int(AddressLen) * 1)) +} + +// HostRead reads a byte slice into a Host value. +func HostRead(buf []byte, v *Host) int { + b := 0 + + v.Family = buf[b] + b += 1 + + b += 1 // padding + + v.AddressLen = xgb.Get16(buf[b:]) + b += 2 + + v.Address = make([]byte, v.AddressLen) + copy(v.Address[:v.AddressLen], buf[b:]) + b += int(v.AddressLen) + + return b +} + +// HostReadList reads a byte slice into a list of Host values. +func HostReadList(buf []byte, dest []Host) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Host{} + b += HostRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Host value to a byte slice. +func (v Host) Bytes() []byte { + buf := make([]byte, (4 + xgb.Pad((int(v.AddressLen) * 1)))) + b := 0 + + buf[b] = v.Family + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], v.AddressLen) + b += 2 + + copy(buf[b:], v.Address[:v.AddressLen]) + b += int(v.AddressLen) + + return buf[:b] +} + +// HostListBytes writes a list of Host values to a byte slice. +func HostListBytes(buf []byte, list []Host) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// HostListSize computes the size (bytes) of a list of Host values. +func HostListSize(list []Host) int { + size := 0 + for _, item := range list { + size += (4 + xgb.Pad((int(item.AddressLen) * 1))) + } + return size +} + +const ( + HostModeInsert = 0 + HostModeDelete = 1 +) + +// BadIDChoice is the error number for a BadIDChoice. +const BadIDChoice = 14 + +type IDChoiceError ValueError + +// IDChoiceErrorNew constructs a IDChoiceError value that implements xgb.Error from a byte slice. +func IDChoiceErrorNew(buf []byte) xgb.Error { + v := IDChoiceError(ValueErrorNew(buf).(ValueError)) + v.NiceName = "IDChoice" + return v +} + +// SequenceId returns the sequence id attached to the BadIDChoice error. +// This is mostly used internally. +func (err IDChoiceError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadIDChoice error. If no bad value exists, 0 is returned. +func (err IDChoiceError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadIDChoice error. +func (err IDChoiceError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadIDChoice {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[14] = IDChoiceErrorNew +} + +const ( + ImageFormatXYBitmap = 0 + ImageFormatXYPixmap = 1 + ImageFormatZPixmap = 2 +) + +const ( + ImageOrderLSBFirst = 0 + ImageOrderMSBFirst = 1 +) + +// BadImplementation is the error number for a BadImplementation. +const BadImplementation = 17 + +type ImplementationError RequestError + +// ImplementationErrorNew constructs a ImplementationError value that implements xgb.Error from a byte slice. +func ImplementationErrorNew(buf []byte) xgb.Error { + v := ImplementationError(RequestErrorNew(buf).(RequestError)) + v.NiceName = "Implementation" + return v +} + +// SequenceId returns the sequence id attached to the BadImplementation error. +// This is mostly used internally. +func (err ImplementationError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadImplementation error. If no bad value exists, 0 is returned. +func (err ImplementationError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadImplementation error. +func (err ImplementationError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadImplementation {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[17] = ImplementationErrorNew +} + +const ( + InputFocusNone = 0 + InputFocusPointerRoot = 1 + InputFocusParent = 2 + InputFocusFollowKeyboard = 3 +) + +const ( + JoinStyleMiter = 0 + JoinStyleRound = 1 + JoinStyleBevel = 2 +) + +const ( + KbKeyClickPercent = 1 + KbBellPercent = 2 + KbBellPitch = 4 + KbBellDuration = 8 + KbLed = 16 + KbLedMode = 32 + KbKey = 64 + KbAutoRepeatMode = 128 +) + +const ( + KeyButMaskShift = 1 + KeyButMaskLock = 2 + KeyButMaskControl = 4 + KeyButMaskMod1 = 8 + KeyButMaskMod2 = 16 + KeyButMaskMod3 = 32 + KeyButMaskMod4 = 64 + KeyButMaskMod5 = 128 + KeyButMaskButton1 = 256 + KeyButMaskButton2 = 512 + KeyButMaskButton3 = 1024 + KeyButMaskButton4 = 2048 + KeyButMaskButton5 = 4096 +) + +// KeyPress is the event number for a KeyPressEvent. +const KeyPress = 2 + +type KeyPressEvent struct { + Sequence uint16 + Detail Keycode + Time Timestamp + Root Window + Event Window + Child Window + RootX int16 + RootY int16 + EventX int16 + EventY int16 + State uint16 + SameScreen bool + // padding: 1 bytes +} + +// KeyPressEventNew constructs a KeyPressEvent value that implements xgb.Event from a byte slice. +func KeyPressEventNew(buf []byte) xgb.Event { + v := KeyPressEvent{} + b := 1 // don't read event number + + v.Detail = Keycode(buf[b]) + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Time = Timestamp(xgb.Get32(buf[b:])) + b += 4 + + v.Root = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Child = Window(xgb.Get32(buf[b:])) + b += 4 + + v.RootX = int16(xgb.Get16(buf[b:])) + b += 2 + + v.RootY = int16(xgb.Get16(buf[b:])) + b += 2 + + v.EventX = int16(xgb.Get16(buf[b:])) + b += 2 + + v.EventY = int16(xgb.Get16(buf[b:])) + b += 2 + + v.State = xgb.Get16(buf[b:]) + b += 2 + + if buf[b] == 1 { + v.SameScreen = true + } else { + v.SameScreen = false + } + b += 1 + + b += 1 // padding + + return v +} + +// Bytes writes a KeyPressEvent value to a byte slice. +func (v KeyPressEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 2 + b += 1 + + buf[b] = byte(v.Detail) + b += 1 + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Time)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Root)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Child)) + b += 4 + + xgb.Put16(buf[b:], uint16(v.RootX)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.RootY)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.EventX)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.EventY)) + b += 2 + + xgb.Put16(buf[b:], v.State) + b += 2 + + if v.SameScreen { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + b += 1 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the KeyPress event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v KeyPressEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of KeyPressEvent. +func (v KeyPressEvent) String() string { + fieldVals := make([]string, 0, 12) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Detail: %d", v.Detail)) + fieldVals = append(fieldVals, xgb.Sprintf("Time: %d", v.Time)) + fieldVals = append(fieldVals, xgb.Sprintf("Root: %d", v.Root)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Child: %d", v.Child)) + fieldVals = append(fieldVals, xgb.Sprintf("RootX: %d", v.RootX)) + fieldVals = append(fieldVals, xgb.Sprintf("RootY: %d", v.RootY)) + fieldVals = append(fieldVals, xgb.Sprintf("EventX: %d", v.EventX)) + fieldVals = append(fieldVals, xgb.Sprintf("EventY: %d", v.EventY)) + fieldVals = append(fieldVals, xgb.Sprintf("State: %d", v.State)) + fieldVals = append(fieldVals, xgb.Sprintf("SameScreen: %t", v.SameScreen)) + return "KeyPress {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[2] = KeyPressEventNew +} + +// KeyRelease is the event number for a KeyReleaseEvent. +const KeyRelease = 3 + +type KeyReleaseEvent KeyPressEvent + +// KeyReleaseEventNew constructs a KeyReleaseEvent value that implements xgb.Event from a byte slice. +func KeyReleaseEventNew(buf []byte) xgb.Event { + return KeyReleaseEvent(KeyPressEventNew(buf).(KeyPressEvent)) +} + +// Bytes writes a KeyReleaseEvent value to a byte slice. +func (v KeyReleaseEvent) Bytes() []byte { + return KeyPressEvent(v).Bytes() +} + +// SequenceId returns the sequence id attached to the KeyRelease event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v KeyReleaseEvent) SequenceId() uint16 { + return v.Sequence +} + +func (v KeyReleaseEvent) String() string { + fieldVals := make([]string, 0, 12) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Detail: %d", v.Detail)) + fieldVals = append(fieldVals, xgb.Sprintf("Time: %d", v.Time)) + fieldVals = append(fieldVals, xgb.Sprintf("Root: %d", v.Root)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Child: %d", v.Child)) + fieldVals = append(fieldVals, xgb.Sprintf("RootX: %d", v.RootX)) + fieldVals = append(fieldVals, xgb.Sprintf("RootY: %d", v.RootY)) + fieldVals = append(fieldVals, xgb.Sprintf("EventX: %d", v.EventX)) + fieldVals = append(fieldVals, xgb.Sprintf("EventY: %d", v.EventY)) + fieldVals = append(fieldVals, xgb.Sprintf("State: %d", v.State)) + fieldVals = append(fieldVals, xgb.Sprintf("SameScreen: %t", v.SameScreen)) + return "KeyRelease {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[3] = KeyReleaseEventNew +} + +type Keycode byte + +// KeymapNotify is the event number for a KeymapNotifyEvent. +const KeymapNotify = 11 + +type KeymapNotifyEvent struct { + Keys []byte // size: 32 +} + +// KeymapNotifyEventNew constructs a KeymapNotifyEvent value that implements xgb.Event from a byte slice. +func KeymapNotifyEventNew(buf []byte) xgb.Event { + v := KeymapNotifyEvent{} + b := 1 // don't read event number + + v.Keys = make([]byte, 31) + copy(v.Keys[:31], buf[b:]) + b += int(31) + + return v +} + +// Bytes writes a KeymapNotifyEvent value to a byte slice. +func (v KeymapNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 11 + b += 1 + + copy(buf[b:], v.Keys[:31]) + b += int(31) + + return buf +} + +// SequenceId returns the sequence id attached to the KeymapNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v KeymapNotifyEvent) SequenceId() uint16 { + return uint16(0) +} + +// String is a rudimentary string representation of KeymapNotifyEvent. +func (v KeymapNotifyEvent) String() string { + fieldVals := make([]string, 0, 1) + return "KeymapNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[11] = KeymapNotifyEventNew +} + +type Keysym uint32 + +const ( + KillAllTemporary = 0 +) + +// LeaveNotify is the event number for a LeaveNotifyEvent. +const LeaveNotify = 8 + +type LeaveNotifyEvent EnterNotifyEvent + +// LeaveNotifyEventNew constructs a LeaveNotifyEvent value that implements xgb.Event from a byte slice. +func LeaveNotifyEventNew(buf []byte) xgb.Event { + return LeaveNotifyEvent(EnterNotifyEventNew(buf).(EnterNotifyEvent)) +} + +// Bytes writes a LeaveNotifyEvent value to a byte slice. +func (v LeaveNotifyEvent) Bytes() []byte { + return EnterNotifyEvent(v).Bytes() +} + +// SequenceId returns the sequence id attached to the LeaveNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v LeaveNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +func (v LeaveNotifyEvent) String() string { + fieldVals := make([]string, 0, 12) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Detail: %d", v.Detail)) + fieldVals = append(fieldVals, xgb.Sprintf("Time: %d", v.Time)) + fieldVals = append(fieldVals, xgb.Sprintf("Root: %d", v.Root)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Child: %d", v.Child)) + fieldVals = append(fieldVals, xgb.Sprintf("RootX: %d", v.RootX)) + fieldVals = append(fieldVals, xgb.Sprintf("RootY: %d", v.RootY)) + fieldVals = append(fieldVals, xgb.Sprintf("EventX: %d", v.EventX)) + fieldVals = append(fieldVals, xgb.Sprintf("EventY: %d", v.EventY)) + fieldVals = append(fieldVals, xgb.Sprintf("State: %d", v.State)) + fieldVals = append(fieldVals, xgb.Sprintf("Mode: %d", v.Mode)) + fieldVals = append(fieldVals, xgb.Sprintf("SameScreenFocus: %d", v.SameScreenFocus)) + return "LeaveNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[8] = LeaveNotifyEventNew +} + +const ( + LedModeOff = 0 + LedModeOn = 1 +) + +// BadLength is the error number for a BadLength. +const BadLength = 16 + +type LengthError RequestError + +// LengthErrorNew constructs a LengthError value that implements xgb.Error from a byte slice. +func LengthErrorNew(buf []byte) xgb.Error { + v := LengthError(RequestErrorNew(buf).(RequestError)) + v.NiceName = "Length" + return v +} + +// SequenceId returns the sequence id attached to the BadLength error. +// This is mostly used internally. +func (err LengthError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadLength error. If no bad value exists, 0 is returned. +func (err LengthError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadLength error. +func (err LengthError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadLength {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[16] = LengthErrorNew +} + +const ( + LineStyleSolid = 0 + LineStyleOnOffDash = 1 + LineStyleDoubleDash = 2 +) + +const ( + MapIndexShift = 0 + MapIndexLock = 1 + MapIndexControl = 2 + MapIndex1 = 3 + MapIndex2 = 4 + MapIndex3 = 5 + MapIndex4 = 6 + MapIndex5 = 7 +) + +// MapNotify is the event number for a MapNotifyEvent. +const MapNotify = 19 + +type MapNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Event Window + Window Window + OverrideRedirect bool + // padding: 3 bytes +} + +// MapNotifyEventNew constructs a MapNotifyEvent value that implements xgb.Event from a byte slice. +func MapNotifyEventNew(buf []byte) xgb.Event { + v := MapNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + if buf[b] == 1 { + v.OverrideRedirect = true + } else { + v.OverrideRedirect = false + } + b += 1 + + b += 3 // padding + + return v +} + +// Bytes writes a MapNotifyEvent value to a byte slice. +func (v MapNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 19 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + if v.OverrideRedirect { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + b += 3 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the MapNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v MapNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of MapNotifyEvent. +func (v MapNotifyEvent) String() string { + fieldVals := make([]string, 0, 5) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("OverrideRedirect: %t", v.OverrideRedirect)) + return "MapNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[19] = MapNotifyEventNew +} + +// MapRequest is the event number for a MapRequestEvent. +const MapRequest = 20 + +type MapRequestEvent struct { + Sequence uint16 + // padding: 1 bytes + Parent Window + Window Window +} + +// MapRequestEventNew constructs a MapRequestEvent value that implements xgb.Event from a byte slice. +func MapRequestEventNew(buf []byte) xgb.Event { + v := MapRequestEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Parent = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + return v +} + +// Bytes writes a MapRequestEvent value to a byte slice. +func (v MapRequestEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 20 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Parent)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + return buf +} + +// SequenceId returns the sequence id attached to the MapRequest event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v MapRequestEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of MapRequestEvent. +func (v MapRequestEvent) String() string { + fieldVals := make([]string, 0, 3) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Parent: %d", v.Parent)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + return "MapRequest {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[20] = MapRequestEventNew +} + +const ( + MapStateUnmapped = 0 + MapStateUnviewable = 1 + MapStateViewable = 2 +) + +const ( + MappingModifier = 0 + MappingKeyboard = 1 + MappingPointer = 2 +) + +// MappingNotify is the event number for a MappingNotifyEvent. +const MappingNotify = 34 + +type MappingNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Request byte + FirstKeycode Keycode + Count byte + // padding: 1 bytes +} + +// MappingNotifyEventNew constructs a MappingNotifyEvent value that implements xgb.Event from a byte slice. +func MappingNotifyEventNew(buf []byte) xgb.Event { + v := MappingNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Request = buf[b] + b += 1 + + v.FirstKeycode = Keycode(buf[b]) + b += 1 + + v.Count = buf[b] + b += 1 + + b += 1 // padding + + return v +} + +// Bytes writes a MappingNotifyEvent value to a byte slice. +func (v MappingNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 34 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + buf[b] = v.Request + b += 1 + + buf[b] = byte(v.FirstKeycode) + b += 1 + + buf[b] = v.Count + b += 1 + + b += 1 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the MappingNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v MappingNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of MappingNotifyEvent. +func (v MappingNotifyEvent) String() string { + fieldVals := make([]string, 0, 5) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Request: %d", v.Request)) + fieldVals = append(fieldVals, xgb.Sprintf("FirstKeycode: %d", v.FirstKeycode)) + fieldVals = append(fieldVals, xgb.Sprintf("Count: %d", v.Count)) + return "MappingNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[34] = MappingNotifyEventNew +} + +const ( + MappingStatusSuccess = 0 + MappingStatusBusy = 1 + MappingStatusFailure = 2 +) + +// BadMatch is the error number for a BadMatch. +const BadMatch = 8 + +type MatchError RequestError + +// MatchErrorNew constructs a MatchError value that implements xgb.Error from a byte slice. +func MatchErrorNew(buf []byte) xgb.Error { + v := MatchError(RequestErrorNew(buf).(RequestError)) + v.NiceName = "Match" + return v +} + +// SequenceId returns the sequence id attached to the BadMatch error. +// This is mostly used internally. +func (err MatchError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadMatch error. If no bad value exists, 0 is returned. +func (err MatchError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadMatch error. +func (err MatchError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadMatch {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[8] = MatchErrorNew +} + +const ( + ModMaskShift = 1 + ModMaskLock = 2 + ModMaskControl = 4 + ModMask1 = 8 + ModMask2 = 16 + ModMask3 = 32 + ModMask4 = 64 + ModMask5 = 128 + ModMaskAny = 32768 +) + +const ( + MotionNormal = 0 + MotionHint = 1 +) + +// MotionNotify is the event number for a MotionNotifyEvent. +const MotionNotify = 6 + +type MotionNotifyEvent struct { + Sequence uint16 + Detail byte + Time Timestamp + Root Window + Event Window + Child Window + RootX int16 + RootY int16 + EventX int16 + EventY int16 + State uint16 + SameScreen bool + // padding: 1 bytes +} + +// MotionNotifyEventNew constructs a MotionNotifyEvent value that implements xgb.Event from a byte slice. +func MotionNotifyEventNew(buf []byte) xgb.Event { + v := MotionNotifyEvent{} + b := 1 // don't read event number + + v.Detail = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Time = Timestamp(xgb.Get32(buf[b:])) + b += 4 + + v.Root = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Child = Window(xgb.Get32(buf[b:])) + b += 4 + + v.RootX = int16(xgb.Get16(buf[b:])) + b += 2 + + v.RootY = int16(xgb.Get16(buf[b:])) + b += 2 + + v.EventX = int16(xgb.Get16(buf[b:])) + b += 2 + + v.EventY = int16(xgb.Get16(buf[b:])) + b += 2 + + v.State = xgb.Get16(buf[b:]) + b += 2 + + if buf[b] == 1 { + v.SameScreen = true + } else { + v.SameScreen = false + } + b += 1 + + b += 1 // padding + + return v +} + +// Bytes writes a MotionNotifyEvent value to a byte slice. +func (v MotionNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 6 + b += 1 + + buf[b] = v.Detail + b += 1 + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Time)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Root)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Child)) + b += 4 + + xgb.Put16(buf[b:], uint16(v.RootX)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.RootY)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.EventX)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.EventY)) + b += 2 + + xgb.Put16(buf[b:], v.State) + b += 2 + + if v.SameScreen { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + b += 1 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the MotionNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v MotionNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of MotionNotifyEvent. +func (v MotionNotifyEvent) String() string { + fieldVals := make([]string, 0, 12) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Detail: %d", v.Detail)) + fieldVals = append(fieldVals, xgb.Sprintf("Time: %d", v.Time)) + fieldVals = append(fieldVals, xgb.Sprintf("Root: %d", v.Root)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Child: %d", v.Child)) + fieldVals = append(fieldVals, xgb.Sprintf("RootX: %d", v.RootX)) + fieldVals = append(fieldVals, xgb.Sprintf("RootY: %d", v.RootY)) + fieldVals = append(fieldVals, xgb.Sprintf("EventX: %d", v.EventX)) + fieldVals = append(fieldVals, xgb.Sprintf("EventY: %d", v.EventY)) + fieldVals = append(fieldVals, xgb.Sprintf("State: %d", v.State)) + fieldVals = append(fieldVals, xgb.Sprintf("SameScreen: %t", v.SameScreen)) + return "MotionNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[6] = MotionNotifyEventNew +} + +// BadName is the error number for a BadName. +const BadName = 15 + +type NameError RequestError + +// NameErrorNew constructs a NameError value that implements xgb.Error from a byte slice. +func NameErrorNew(buf []byte) xgb.Error { + v := NameError(RequestErrorNew(buf).(RequestError)) + v.NiceName = "Name" + return v +} + +// SequenceId returns the sequence id attached to the BadName error. +// This is mostly used internally. +func (err NameError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadName error. If no bad value exists, 0 is returned. +func (err NameError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadName error. +func (err NameError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadName {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[15] = NameErrorNew +} + +// NoExposure is the event number for a NoExposureEvent. +const NoExposure = 14 + +type NoExposureEvent struct { + Sequence uint16 + // padding: 1 bytes + Drawable Drawable + MinorOpcode uint16 + MajorOpcode byte + // padding: 1 bytes +} + +// NoExposureEventNew constructs a NoExposureEvent value that implements xgb.Event from a byte slice. +func NoExposureEventNew(buf []byte) xgb.Event { + v := NoExposureEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Drawable = Drawable(xgb.Get32(buf[b:])) + b += 4 + + v.MinorOpcode = xgb.Get16(buf[b:]) + b += 2 + + v.MajorOpcode = buf[b] + b += 1 + + b += 1 // padding + + return v +} + +// Bytes writes a NoExposureEvent value to a byte slice. +func (v NoExposureEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 14 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Drawable)) + b += 4 + + xgb.Put16(buf[b:], v.MinorOpcode) + b += 2 + + buf[b] = v.MajorOpcode + b += 1 + + b += 1 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the NoExposure event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v NoExposureEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of NoExposureEvent. +func (v NoExposureEvent) String() string { + fieldVals := make([]string, 0, 5) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Drawable: %d", v.Drawable)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", v.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", v.MajorOpcode)) + return "NoExposure {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[14] = NoExposureEventNew +} + +const ( + NotifyDetailAncestor = 0 + NotifyDetailVirtual = 1 + NotifyDetailInferior = 2 + NotifyDetailNonlinear = 3 + NotifyDetailNonlinearVirtual = 4 + NotifyDetailPointer = 5 + NotifyDetailPointerRoot = 6 + NotifyDetailNone = 7 +) + +const ( + NotifyModeNormal = 0 + NotifyModeGrab = 1 + NotifyModeUngrab = 2 + NotifyModeWhileGrabbed = 3 +) + +type Pixmap uint32 + +func NewPixmapId(c *xgb.Conn) (Pixmap, error) { + id, err := c.NewId() + if err != nil { + return 0, err + } + return Pixmap(id), nil +} + +const ( + PixmapNone = 0 +) + +// BadPixmap is the error number for a BadPixmap. +const BadPixmap = 4 + +type PixmapError ValueError + +// PixmapErrorNew constructs a PixmapError value that implements xgb.Error from a byte slice. +func PixmapErrorNew(buf []byte) xgb.Error { + v := PixmapError(ValueErrorNew(buf).(ValueError)) + v.NiceName = "Pixmap" + return v +} + +// SequenceId returns the sequence id attached to the BadPixmap error. +// This is mostly used internally. +func (err PixmapError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadPixmap error. If no bad value exists, 0 is returned. +func (err PixmapError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadPixmap error. +func (err PixmapError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadPixmap {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[4] = PixmapErrorNew +} + +const ( + PlaceOnTop = 0 + PlaceOnBottom = 1 +) + +type Point struct { + X int16 + Y int16 +} + +// PointRead reads a byte slice into a Point value. +func PointRead(buf []byte, v *Point) int { + b := 0 + + v.X = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y = int16(xgb.Get16(buf[b:])) + b += 2 + + return b +} + +// PointReadList reads a byte slice into a list of Point values. +func PointReadList(buf []byte, dest []Point) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Point{} + b += PointRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Point value to a byte slice. +func (v Point) Bytes() []byte { + buf := make([]byte, 4) + b := 0 + + xgb.Put16(buf[b:], uint16(v.X)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Y)) + b += 2 + + return buf[:b] +} + +// PointListBytes writes a list of Point values to a byte slice. +func PointListBytes(buf []byte, list []Point) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +const ( + PolyShapeComplex = 0 + PolyShapeNonconvex = 1 + PolyShapeConvex = 2 +) + +const ( + PropModeReplace = 0 + PropModePrepend = 1 + PropModeAppend = 2 +) + +const ( + PropertyNewValue = 0 + PropertyDelete = 1 +) + +// PropertyNotify is the event number for a PropertyNotifyEvent. +const PropertyNotify = 28 + +type PropertyNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Window Window + Atom Atom + Time Timestamp + State byte + // padding: 3 bytes +} + +// PropertyNotifyEventNew constructs a PropertyNotifyEvent value that implements xgb.Event from a byte slice. +func PropertyNotifyEventNew(buf []byte) xgb.Event { + v := PropertyNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Atom = Atom(xgb.Get32(buf[b:])) + b += 4 + + v.Time = Timestamp(xgb.Get32(buf[b:])) + b += 4 + + v.State = buf[b] + b += 1 + + b += 3 // padding + + return v +} + +// Bytes writes a PropertyNotifyEvent value to a byte slice. +func (v PropertyNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 28 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Atom)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Time)) + b += 4 + + buf[b] = v.State + b += 1 + + b += 3 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the PropertyNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v PropertyNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of PropertyNotifyEvent. +func (v PropertyNotifyEvent) String() string { + fieldVals := make([]string, 0, 6) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("Atom: %d", v.Atom)) + fieldVals = append(fieldVals, xgb.Sprintf("Time: %d", v.Time)) + fieldVals = append(fieldVals, xgb.Sprintf("State: %d", v.State)) + return "PropertyNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[28] = PropertyNotifyEventNew +} + +const ( + QueryShapeOfLargestCursor = 0 + QueryShapeOfFastestTile = 1 + QueryShapeOfFastestStipple = 2 +) + +type Rectangle struct { + X int16 + Y int16 + Width uint16 + Height uint16 +} + +// RectangleRead reads a byte slice into a Rectangle value. +func RectangleRead(buf []byte, v *Rectangle) int { + b := 0 + + v.X = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y = 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 +} + +// RectangleReadList reads a byte slice into a list of Rectangle values. +func RectangleReadList(buf []byte, dest []Rectangle) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Rectangle{} + b += RectangleRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Rectangle value to a byte slice. +func (v Rectangle) Bytes() []byte { + buf := make([]byte, 8) + b := 0 + + xgb.Put16(buf[b:], uint16(v.X)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Y)) + b += 2 + + xgb.Put16(buf[b:], v.Width) + b += 2 + + xgb.Put16(buf[b:], v.Height) + b += 2 + + return buf[:b] +} + +// RectangleListBytes writes a list of Rectangle values to a byte slice. +func RectangleListBytes(buf []byte, list []Rectangle) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// ReparentNotify is the event number for a ReparentNotifyEvent. +const ReparentNotify = 21 + +type ReparentNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Event Window + Window Window + Parent Window + X int16 + Y int16 + OverrideRedirect bool + // padding: 3 bytes +} + +// ReparentNotifyEventNew constructs a ReparentNotifyEvent value that implements xgb.Event from a byte slice. +func ReparentNotifyEventNew(buf []byte) xgb.Event { + v := ReparentNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Parent = Window(xgb.Get32(buf[b:])) + b += 4 + + v.X = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y = int16(xgb.Get16(buf[b:])) + b += 2 + + if buf[b] == 1 { + v.OverrideRedirect = true + } else { + v.OverrideRedirect = false + } + b += 1 + + b += 3 // padding + + return v +} + +// Bytes writes a ReparentNotifyEvent value to a byte slice. +func (v ReparentNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 21 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Parent)) + b += 4 + + xgb.Put16(buf[b:], uint16(v.X)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Y)) + b += 2 + + if v.OverrideRedirect { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + b += 3 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the ReparentNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v ReparentNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of ReparentNotifyEvent. +func (v ReparentNotifyEvent) String() string { + fieldVals := make([]string, 0, 8) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("Parent: %d", v.Parent)) + fieldVals = append(fieldVals, xgb.Sprintf("X: %d", v.X)) + fieldVals = append(fieldVals, xgb.Sprintf("Y: %d", v.Y)) + fieldVals = append(fieldVals, xgb.Sprintf("OverrideRedirect: %t", v.OverrideRedirect)) + return "ReparentNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[21] = ReparentNotifyEventNew +} + +// BadRequest is the error number for a BadRequest. +const BadRequest = 1 + +type RequestError struct { + Sequence uint16 + NiceName string + BadValue uint32 + MinorOpcode uint16 + MajorOpcode byte + // padding: 1 bytes +} + +// RequestErrorNew constructs a RequestError value that implements xgb.Error from a byte slice. +func RequestErrorNew(buf []byte) xgb.Error { + v := RequestError{} + v.NiceName = "Request" + + b := 1 // skip error determinant + b += 1 // don't read error number + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.BadValue = xgb.Get32(buf[b:]) + b += 4 + + v.MinorOpcode = xgb.Get16(buf[b:]) + b += 2 + + v.MajorOpcode = buf[b] + b += 1 + + b += 1 // padding + + return v +} + +// SequenceId returns the sequence id attached to the BadRequest error. +// This is mostly used internally. +func (err RequestError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadRequest error. If no bad value exists, 0 is returned. +func (err RequestError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadRequest error. + +func (err RequestError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadRequest {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[1] = RequestErrorNew +} + +// ResizeRequest is the event number for a ResizeRequestEvent. +const ResizeRequest = 25 + +type ResizeRequestEvent struct { + Sequence uint16 + // padding: 1 bytes + Window Window + Width uint16 + Height uint16 +} + +// ResizeRequestEventNew constructs a ResizeRequestEvent value that implements xgb.Event from a byte slice. +func ResizeRequestEventNew(buf []byte) xgb.Event { + v := ResizeRequestEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Width = xgb.Get16(buf[b:]) + b += 2 + + v.Height = xgb.Get16(buf[b:]) + b += 2 + + return v +} + +// Bytes writes a ResizeRequestEvent value to a byte slice. +func (v ResizeRequestEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 25 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + xgb.Put16(buf[b:], v.Width) + b += 2 + + xgb.Put16(buf[b:], v.Height) + b += 2 + + return buf +} + +// SequenceId returns the sequence id attached to the ResizeRequest event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v ResizeRequestEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of ResizeRequestEvent. +func (v ResizeRequestEvent) String() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("Width: %d", v.Width)) + fieldVals = append(fieldVals, xgb.Sprintf("Height: %d", v.Height)) + return "ResizeRequest {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[25] = ResizeRequestEventNew +} + +type Rgb struct { + Red uint16 + Green uint16 + Blue uint16 + // padding: 2 bytes +} + +// RgbRead reads a byte slice into a Rgb value. +func RgbRead(buf []byte, v *Rgb) int { + b := 0 + + v.Red = xgb.Get16(buf[b:]) + b += 2 + + v.Green = xgb.Get16(buf[b:]) + b += 2 + + v.Blue = xgb.Get16(buf[b:]) + b += 2 + + b += 2 // padding + + return b +} + +// RgbReadList reads a byte slice into a list of Rgb values. +func RgbReadList(buf []byte, dest []Rgb) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Rgb{} + b += RgbRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Rgb value to a byte slice. +func (v Rgb) Bytes() []byte { + buf := make([]byte, 8) + b := 0 + + xgb.Put16(buf[b:], v.Red) + b += 2 + + xgb.Put16(buf[b:], v.Green) + b += 2 + + xgb.Put16(buf[b:], v.Blue) + b += 2 + + b += 2 // padding + + return buf[:b] +} + +// RgbListBytes writes a list of Rgb values to a byte slice. +func RgbListBytes(buf []byte, list []Rgb) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +type ScreenInfo struct { + Root Window + DefaultColormap Colormap + WhitePixel uint32 + BlackPixel uint32 + CurrentInputMasks uint32 + WidthInPixels uint16 + HeightInPixels uint16 + WidthInMillimeters uint16 + HeightInMillimeters uint16 + MinInstalledMaps uint16 + MaxInstalledMaps uint16 + RootVisual Visualid + BackingStores byte + SaveUnders bool + RootDepth byte + AllowedDepthsLen byte + AllowedDepths []DepthInfo // size: DepthInfoListSize(AllowedDepths) +} + +// ScreenInfoRead reads a byte slice into a ScreenInfo value. +func ScreenInfoRead(buf []byte, v *ScreenInfo) int { + b := 0 + + v.Root = Window(xgb.Get32(buf[b:])) + b += 4 + + v.DefaultColormap = Colormap(xgb.Get32(buf[b:])) + b += 4 + + v.WhitePixel = xgb.Get32(buf[b:]) + b += 4 + + v.BlackPixel = xgb.Get32(buf[b:]) + b += 4 + + v.CurrentInputMasks = xgb.Get32(buf[b:]) + b += 4 + + v.WidthInPixels = xgb.Get16(buf[b:]) + b += 2 + + v.HeightInPixels = xgb.Get16(buf[b:]) + b += 2 + + v.WidthInMillimeters = xgb.Get16(buf[b:]) + b += 2 + + v.HeightInMillimeters = xgb.Get16(buf[b:]) + b += 2 + + v.MinInstalledMaps = xgb.Get16(buf[b:]) + b += 2 + + v.MaxInstalledMaps = xgb.Get16(buf[b:]) + b += 2 + + v.RootVisual = Visualid(xgb.Get32(buf[b:])) + b += 4 + + v.BackingStores = buf[b] + b += 1 + + if buf[b] == 1 { + v.SaveUnders = true + } else { + v.SaveUnders = false + } + b += 1 + + v.RootDepth = buf[b] + b += 1 + + v.AllowedDepthsLen = buf[b] + b += 1 + + v.AllowedDepths = make([]DepthInfo, v.AllowedDepthsLen) + b += DepthInfoReadList(buf[b:], v.AllowedDepths) + + 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, (40 + DepthInfoListSize(v.AllowedDepths))) + b := 0 + + xgb.Put32(buf[b:], uint32(v.Root)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.DefaultColormap)) + b += 4 + + xgb.Put32(buf[b:], v.WhitePixel) + b += 4 + + xgb.Put32(buf[b:], v.BlackPixel) + b += 4 + + xgb.Put32(buf[b:], v.CurrentInputMasks) + b += 4 + + xgb.Put16(buf[b:], v.WidthInPixels) + b += 2 + + xgb.Put16(buf[b:], v.HeightInPixels) + b += 2 + + xgb.Put16(buf[b:], v.WidthInMillimeters) + b += 2 + + xgb.Put16(buf[b:], v.HeightInMillimeters) + b += 2 + + xgb.Put16(buf[b:], v.MinInstalledMaps) + b += 2 + + xgb.Put16(buf[b:], v.MaxInstalledMaps) + b += 2 + + xgb.Put32(buf[b:], uint32(v.RootVisual)) + b += 4 + + buf[b] = v.BackingStores + b += 1 + + if v.SaveUnders { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + buf[b] = v.RootDepth + b += 1 + + buf[b] = v.AllowedDepthsLen + b += 1 + + b += DepthInfoListBytes(buf[b:], v.AllowedDepths) + + 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) +} + +// ScreenInfoListSize computes the size (bytes) of a list of ScreenInfo values. +func ScreenInfoListSize(list []ScreenInfo) int { + size := 0 + for _, item := range list { + size += (40 + DepthInfoListSize(item.AllowedDepths)) + } + return size +} + +const ( + ScreenSaverReset = 0 + ScreenSaverActive = 1 +) + +type Segment struct { + X1 int16 + Y1 int16 + X2 int16 + Y2 int16 +} + +// SegmentRead reads a byte slice into a Segment value. +func SegmentRead(buf []byte, v *Segment) int { + b := 0 + + v.X1 = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y1 = int16(xgb.Get16(buf[b:])) + b += 2 + + v.X2 = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y2 = int16(xgb.Get16(buf[b:])) + b += 2 + + return b +} + +// SegmentReadList reads a byte slice into a list of Segment values. +func SegmentReadList(buf []byte, dest []Segment) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Segment{} + b += SegmentRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Segment value to a byte slice. +func (v Segment) Bytes() []byte { + buf := make([]byte, 8) + b := 0 + + xgb.Put16(buf[b:], uint16(v.X1)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Y1)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.X2)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Y2)) + b += 2 + + return buf[:b] +} + +// SegmentListBytes writes a list of Segment values to a byte slice. +func SegmentListBytes(buf []byte, list []Segment) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// SelectionClear is the event number for a SelectionClearEvent. +const SelectionClear = 29 + +type SelectionClearEvent struct { + Sequence uint16 + // padding: 1 bytes + Time Timestamp + Owner Window + Selection Atom +} + +// SelectionClearEventNew constructs a SelectionClearEvent value that implements xgb.Event from a byte slice. +func SelectionClearEventNew(buf []byte) xgb.Event { + v := SelectionClearEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Time = Timestamp(xgb.Get32(buf[b:])) + b += 4 + + v.Owner = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Selection = Atom(xgb.Get32(buf[b:])) + b += 4 + + return v +} + +// Bytes writes a SelectionClearEvent value to a byte slice. +func (v SelectionClearEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 29 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Time)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Owner)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Selection)) + b += 4 + + return buf +} + +// SequenceId returns the sequence id attached to the SelectionClear event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v SelectionClearEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of SelectionClearEvent. +func (v SelectionClearEvent) String() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Time: %d", v.Time)) + fieldVals = append(fieldVals, xgb.Sprintf("Owner: %d", v.Owner)) + fieldVals = append(fieldVals, xgb.Sprintf("Selection: %d", v.Selection)) + return "SelectionClear {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[29] = SelectionClearEventNew +} + +// SelectionNotify is the event number for a SelectionNotifyEvent. +const SelectionNotify = 31 + +type SelectionNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Time Timestamp + Requestor Window + Selection Atom + Target Atom + Property Atom +} + +// SelectionNotifyEventNew constructs a SelectionNotifyEvent value that implements xgb.Event from a byte slice. +func SelectionNotifyEventNew(buf []byte) xgb.Event { + v := SelectionNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Time = Timestamp(xgb.Get32(buf[b:])) + b += 4 + + v.Requestor = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Selection = Atom(xgb.Get32(buf[b:])) + b += 4 + + v.Target = Atom(xgb.Get32(buf[b:])) + b += 4 + + v.Property = Atom(xgb.Get32(buf[b:])) + b += 4 + + return v +} + +// Bytes writes a SelectionNotifyEvent value to a byte slice. +func (v SelectionNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 31 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Time)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Requestor)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Selection)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Target)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Property)) + b += 4 + + return buf +} + +// SequenceId returns the sequence id attached to the SelectionNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v SelectionNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of SelectionNotifyEvent. +func (v SelectionNotifyEvent) String() string { + fieldVals := make([]string, 0, 6) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Time: %d", v.Time)) + fieldVals = append(fieldVals, xgb.Sprintf("Requestor: %d", v.Requestor)) + fieldVals = append(fieldVals, xgb.Sprintf("Selection: %d", v.Selection)) + fieldVals = append(fieldVals, xgb.Sprintf("Target: %d", v.Target)) + fieldVals = append(fieldVals, xgb.Sprintf("Property: %d", v.Property)) + return "SelectionNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[31] = SelectionNotifyEventNew +} + +// SelectionRequest is the event number for a SelectionRequestEvent. +const SelectionRequest = 30 + +type SelectionRequestEvent struct { + Sequence uint16 + // padding: 1 bytes + Time Timestamp + Owner Window + Requestor Window + Selection Atom + Target Atom + Property Atom +} + +// SelectionRequestEventNew constructs a SelectionRequestEvent value that implements xgb.Event from a byte slice. +func SelectionRequestEventNew(buf []byte) xgb.Event { + v := SelectionRequestEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Time = Timestamp(xgb.Get32(buf[b:])) + b += 4 + + v.Owner = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Requestor = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Selection = Atom(xgb.Get32(buf[b:])) + b += 4 + + v.Target = Atom(xgb.Get32(buf[b:])) + b += 4 + + v.Property = Atom(xgb.Get32(buf[b:])) + b += 4 + + return v +} + +// Bytes writes a SelectionRequestEvent value to a byte slice. +func (v SelectionRequestEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 30 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Time)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Owner)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Requestor)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Selection)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Target)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Property)) + b += 4 + + return buf +} + +// SequenceId returns the sequence id attached to the SelectionRequest event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v SelectionRequestEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of SelectionRequestEvent. +func (v SelectionRequestEvent) String() string { + fieldVals := make([]string, 0, 7) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Time: %d", v.Time)) + fieldVals = append(fieldVals, xgb.Sprintf("Owner: %d", v.Owner)) + fieldVals = append(fieldVals, xgb.Sprintf("Requestor: %d", v.Requestor)) + fieldVals = append(fieldVals, xgb.Sprintf("Selection: %d", v.Selection)) + fieldVals = append(fieldVals, xgb.Sprintf("Target: %d", v.Target)) + fieldVals = append(fieldVals, xgb.Sprintf("Property: %d", v.Property)) + return "SelectionRequest {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[30] = SelectionRequestEventNew +} + +const ( + SendEventDestPointerWindow = 0 + SendEventDestItemFocus = 1 +) + +const ( + SetModeInsert = 0 + SetModeDelete = 1 +) + +type SetupAuthenticate struct { + Status byte + // padding: 5 bytes + Length uint16 + Reason string // size: xgb.Pad(((int(Length) * 4) * 1)) +} + +// SetupAuthenticateRead reads a byte slice into a SetupAuthenticate value. +func SetupAuthenticateRead(buf []byte, v *SetupAuthenticate) int { + b := 0 + + v.Status = buf[b] + b += 1 + + b += 5 // padding + + v.Length = xgb.Get16(buf[b:]) + b += 2 + + { + byteString := make([]byte, (int(v.Length) * 4)) + copy(byteString[:(int(v.Length)*4)], buf[b:]) + v.Reason = string(byteString) + b += int((int(v.Length) * 4)) + } + + return b +} + +// SetupAuthenticateReadList reads a byte slice into a list of SetupAuthenticate values. +func SetupAuthenticateReadList(buf []byte, dest []SetupAuthenticate) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = SetupAuthenticate{} + b += SetupAuthenticateRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a SetupAuthenticate value to a byte slice. +func (v SetupAuthenticate) Bytes() []byte { + buf := make([]byte, (8 + xgb.Pad(((int(v.Length) * 4) * 1)))) + b := 0 + + buf[b] = v.Status + b += 1 + + b += 5 // padding + + xgb.Put16(buf[b:], v.Length) + b += 2 + + copy(buf[b:], v.Reason[:(int(v.Length)*4)]) + b += int((int(v.Length) * 4)) + + return buf[:b] +} + +// SetupAuthenticateListBytes writes a list of SetupAuthenticate values to a byte slice. +func SetupAuthenticateListBytes(buf []byte, list []SetupAuthenticate) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// SetupAuthenticateListSize computes the size (bytes) of a list of SetupAuthenticate values. +func SetupAuthenticateListSize(list []SetupAuthenticate) int { + size := 0 + for _, item := range list { + size += (8 + xgb.Pad(((int(item.Length) * 4) * 1))) + } + return size +} + +type SetupFailed struct { + Status byte + ReasonLen byte + ProtocolMajorVersion uint16 + ProtocolMinorVersion uint16 + Length uint16 + Reason string // size: xgb.Pad((int(ReasonLen) * 1)) +} + +// SetupFailedRead reads a byte slice into a SetupFailed value. +func SetupFailedRead(buf []byte, v *SetupFailed) int { + b := 0 + + v.Status = buf[b] + b += 1 + + v.ReasonLen = buf[b] + b += 1 + + v.ProtocolMajorVersion = xgb.Get16(buf[b:]) + b += 2 + + v.ProtocolMinorVersion = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get16(buf[b:]) + b += 2 + + { + byteString := make([]byte, v.ReasonLen) + copy(byteString[:v.ReasonLen], buf[b:]) + v.Reason = string(byteString) + b += int(v.ReasonLen) + } + + return b +} + +// SetupFailedReadList reads a byte slice into a list of SetupFailed values. +func SetupFailedReadList(buf []byte, dest []SetupFailed) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = SetupFailed{} + b += SetupFailedRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a SetupFailed value to a byte slice. +func (v SetupFailed) Bytes() []byte { + buf := make([]byte, (8 + xgb.Pad((int(v.ReasonLen) * 1)))) + b := 0 + + buf[b] = v.Status + b += 1 + + buf[b] = v.ReasonLen + b += 1 + + xgb.Put16(buf[b:], v.ProtocolMajorVersion) + b += 2 + + xgb.Put16(buf[b:], v.ProtocolMinorVersion) + b += 2 + + xgb.Put16(buf[b:], v.Length) + b += 2 + + copy(buf[b:], v.Reason[:v.ReasonLen]) + b += int(v.ReasonLen) + + return buf[:b] +} + +// SetupFailedListBytes writes a list of SetupFailed values to a byte slice. +func SetupFailedListBytes(buf []byte, list []SetupFailed) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// SetupFailedListSize computes the size (bytes) of a list of SetupFailed values. +func SetupFailedListSize(list []SetupFailed) int { + size := 0 + for _, item := range list { + size += (8 + xgb.Pad((int(item.ReasonLen) * 1))) + } + return size +} + +type SetupInfo struct { + Status byte + // padding: 1 bytes + ProtocolMajorVersion uint16 + ProtocolMinorVersion uint16 + Length uint16 + ReleaseNumber uint32 + ResourceIdBase uint32 + ResourceIdMask uint32 + MotionBufferSize uint32 + VendorLen uint16 + MaximumRequestLength uint16 + RootsLen byte + PixmapFormatsLen byte + ImageByteOrder byte + BitmapFormatBitOrder byte + BitmapFormatScanlineUnit byte + BitmapFormatScanlinePad byte + MinKeycode Keycode + MaxKeycode Keycode + // padding: 4 bytes + Vendor string // size: xgb.Pad((int(VendorLen) * 1)) + // alignment gap to multiple of 4 + PixmapFormats []Format // size: xgb.Pad((int(PixmapFormatsLen) * 8)) + // alignment gap to multiple of 4 + Roots []ScreenInfo // size: ScreenInfoListSize(Roots) +} + +// SetupInfoRead reads a byte slice into a SetupInfo value. +func SetupInfoRead(buf []byte, v *SetupInfo) int { + b := 0 + + v.Status = buf[b] + b += 1 + + b += 1 // padding + + v.ProtocolMajorVersion = xgb.Get16(buf[b:]) + b += 2 + + v.ProtocolMinorVersion = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get16(buf[b:]) + b += 2 + + v.ReleaseNumber = xgb.Get32(buf[b:]) + b += 4 + + v.ResourceIdBase = xgb.Get32(buf[b:]) + b += 4 + + v.ResourceIdMask = xgb.Get32(buf[b:]) + b += 4 + + v.MotionBufferSize = xgb.Get32(buf[b:]) + b += 4 + + v.VendorLen = xgb.Get16(buf[b:]) + b += 2 + + v.MaximumRequestLength = xgb.Get16(buf[b:]) + b += 2 + + v.RootsLen = buf[b] + b += 1 + + v.PixmapFormatsLen = buf[b] + b += 1 + + v.ImageByteOrder = buf[b] + b += 1 + + v.BitmapFormatBitOrder = buf[b] + b += 1 + + v.BitmapFormatScanlineUnit = buf[b] + b += 1 + + v.BitmapFormatScanlinePad = buf[b] + b += 1 + + v.MinKeycode = Keycode(buf[b]) + b += 1 + + v.MaxKeycode = Keycode(buf[b]) + b += 1 + + b += 4 // padding + + { + byteString := make([]byte, v.VendorLen) + copy(byteString[:v.VendorLen], buf[b:]) + v.Vendor = string(byteString) + b += int(v.VendorLen) + } + + b = (b + 3) & ^3 // alignment gap + + v.PixmapFormats = make([]Format, v.PixmapFormatsLen) + b += FormatReadList(buf[b:], v.PixmapFormats) + + b = (b + 3) & ^3 // alignment gap + + v.Roots = make([]ScreenInfo, v.RootsLen) + b += ScreenInfoReadList(buf[b:], v.Roots) + + return b +} + +// SetupInfoReadList reads a byte slice into a list of SetupInfo values. +func SetupInfoReadList(buf []byte, dest []SetupInfo) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = SetupInfo{} + b += SetupInfoRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a SetupInfo value to a byte slice. +func (v SetupInfo) Bytes() []byte { + buf := make([]byte, (((((40 + xgb.Pad((int(v.VendorLen) * 1))) + 4) + xgb.Pad((int(v.PixmapFormatsLen) * 8))) + 4) + ScreenInfoListSize(v.Roots))) + b := 0 + + buf[b] = v.Status + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], v.ProtocolMajorVersion) + b += 2 + + xgb.Put16(buf[b:], v.ProtocolMinorVersion) + b += 2 + + xgb.Put16(buf[b:], v.Length) + b += 2 + + xgb.Put32(buf[b:], v.ReleaseNumber) + b += 4 + + xgb.Put32(buf[b:], v.ResourceIdBase) + b += 4 + + xgb.Put32(buf[b:], v.ResourceIdMask) + b += 4 + + xgb.Put32(buf[b:], v.MotionBufferSize) + b += 4 + + xgb.Put16(buf[b:], v.VendorLen) + b += 2 + + xgb.Put16(buf[b:], v.MaximumRequestLength) + b += 2 + + buf[b] = v.RootsLen + b += 1 + + buf[b] = v.PixmapFormatsLen + b += 1 + + buf[b] = v.ImageByteOrder + b += 1 + + buf[b] = v.BitmapFormatBitOrder + b += 1 + + buf[b] = v.BitmapFormatScanlineUnit + b += 1 + + buf[b] = v.BitmapFormatScanlinePad + b += 1 + + buf[b] = byte(v.MinKeycode) + b += 1 + + buf[b] = byte(v.MaxKeycode) + b += 1 + + b += 4 // padding + + copy(buf[b:], v.Vendor[:v.VendorLen]) + b += int(v.VendorLen) + + b = (b + 3) & ^3 // alignment gap + + b += FormatListBytes(buf[b:], v.PixmapFormats) + + b = (b + 3) & ^3 // alignment gap + + b += ScreenInfoListBytes(buf[b:], v.Roots) + + return buf[:b] +} + +// SetupInfoListBytes writes a list of SetupInfo values to a byte slice. +func SetupInfoListBytes(buf []byte, list []SetupInfo) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// SetupInfoListSize computes the size (bytes) of a list of SetupInfo values. +func SetupInfoListSize(list []SetupInfo) int { + size := 0 + for _, item := range list { + size += (((((40 + xgb.Pad((int(item.VendorLen) * 1))) + 4) + xgb.Pad((int(item.PixmapFormatsLen) * 8))) + 4) + ScreenInfoListSize(item.Roots)) + } + return size +} + +type SetupRequest struct { + ByteOrder byte + // padding: 1 bytes + ProtocolMajorVersion uint16 + ProtocolMinorVersion uint16 + AuthorizationProtocolNameLen uint16 + AuthorizationProtocolDataLen uint16 + // padding: 2 bytes + AuthorizationProtocolName string // size: xgb.Pad((int(AuthorizationProtocolNameLen) * 1)) + AuthorizationProtocolData string // size: xgb.Pad((int(AuthorizationProtocolDataLen) * 1)) +} + +// SetupRequestRead reads a byte slice into a SetupRequest value. +func SetupRequestRead(buf []byte, v *SetupRequest) int { + b := 0 + + v.ByteOrder = buf[b] + b += 1 + + b += 1 // padding + + v.ProtocolMajorVersion = xgb.Get16(buf[b:]) + b += 2 + + v.ProtocolMinorVersion = xgb.Get16(buf[b:]) + b += 2 + + v.AuthorizationProtocolNameLen = xgb.Get16(buf[b:]) + b += 2 + + v.AuthorizationProtocolDataLen = xgb.Get16(buf[b:]) + b += 2 + + b += 2 // padding + + { + byteString := make([]byte, v.AuthorizationProtocolNameLen) + copy(byteString[:v.AuthorizationProtocolNameLen], buf[b:]) + v.AuthorizationProtocolName = string(byteString) + b += int(v.AuthorizationProtocolNameLen) + } + + { + byteString := make([]byte, v.AuthorizationProtocolDataLen) + copy(byteString[:v.AuthorizationProtocolDataLen], buf[b:]) + v.AuthorizationProtocolData = string(byteString) + b += int(v.AuthorizationProtocolDataLen) + } + + return b +} + +// SetupRequestReadList reads a byte slice into a list of SetupRequest values. +func SetupRequestReadList(buf []byte, dest []SetupRequest) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = SetupRequest{} + b += SetupRequestRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a SetupRequest value to a byte slice. +func (v SetupRequest) Bytes() []byte { + buf := make([]byte, ((12 + xgb.Pad((int(v.AuthorizationProtocolNameLen) * 1))) + xgb.Pad((int(v.AuthorizationProtocolDataLen) * 1)))) + b := 0 + + buf[b] = v.ByteOrder + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], v.ProtocolMajorVersion) + b += 2 + + xgb.Put16(buf[b:], v.ProtocolMinorVersion) + b += 2 + + xgb.Put16(buf[b:], v.AuthorizationProtocolNameLen) + b += 2 + + xgb.Put16(buf[b:], v.AuthorizationProtocolDataLen) + b += 2 + + b += 2 // padding + + copy(buf[b:], v.AuthorizationProtocolName[:v.AuthorizationProtocolNameLen]) + b += int(v.AuthorizationProtocolNameLen) + + copy(buf[b:], v.AuthorizationProtocolData[:v.AuthorizationProtocolDataLen]) + b += int(v.AuthorizationProtocolDataLen) + + return buf[:b] +} + +// SetupRequestListBytes writes a list of SetupRequest values to a byte slice. +func SetupRequestListBytes(buf []byte, list []SetupRequest) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// SetupRequestListSize computes the size (bytes) of a list of SetupRequest values. +func SetupRequestListSize(list []SetupRequest) int { + size := 0 + for _, item := range list { + size += ((12 + xgb.Pad((int(item.AuthorizationProtocolNameLen) * 1))) + xgb.Pad((int(item.AuthorizationProtocolDataLen) * 1))) + } + return size +} + +const ( + StackModeAbove = 0 + StackModeBelow = 1 + StackModeTopIf = 2 + StackModeBottomIf = 3 + StackModeOpposite = 4 +) + +type Str struct { + NameLen byte + Name string // size: xgb.Pad((int(NameLen) * 1)) +} + +// StrRead reads a byte slice into a Str value. +func StrRead(buf []byte, v *Str) int { + b := 0 + + v.NameLen = buf[b] + b += 1 + + { + byteString := make([]byte, v.NameLen) + copy(byteString[:v.NameLen], buf[b:]) + v.Name = string(byteString) + b += int(v.NameLen) + } + + return b +} + +// StrReadList reads a byte slice into a list of Str values. +func StrReadList(buf []byte, dest []Str) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Str{} + b += StrRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Str value to a byte slice. +func (v Str) Bytes() []byte { + buf := make([]byte, (1 + xgb.Pad((int(v.NameLen) * 1)))) + b := 0 + + buf[b] = v.NameLen + b += 1 + + copy(buf[b:], v.Name[:v.NameLen]) + b += int(v.NameLen) + + return buf[:b] +} + +// StrListBytes writes a list of Str values to a byte slice. +func StrListBytes(buf []byte, list []Str) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +// StrListSize computes the size (bytes) of a list of Str values. +func StrListSize(list []Str) int { + size := 0 + for _, item := range list { + size += (1 + xgb.Pad((int(item.NameLen) * 1))) + } + return size +} + +const ( + SubwindowModeClipByChildren = 0 + SubwindowModeIncludeInferiors = 1 +) + +const ( + TimeCurrentTime = 0 +) + +type Timecoord struct { + Time Timestamp + X int16 + Y int16 +} + +// TimecoordRead reads a byte slice into a Timecoord value. +func TimecoordRead(buf []byte, v *Timecoord) int { + b := 0 + + v.Time = Timestamp(xgb.Get32(buf[b:])) + b += 4 + + v.X = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y = int16(xgb.Get16(buf[b:])) + b += 2 + + return b +} + +// TimecoordReadList reads a byte slice into a list of Timecoord values. +func TimecoordReadList(buf []byte, dest []Timecoord) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = Timecoord{} + b += TimecoordRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a Timecoord value to a byte slice. +func (v Timecoord) Bytes() []byte { + buf := make([]byte, 8) + b := 0 + + xgb.Put32(buf[b:], uint32(v.Time)) + b += 4 + + xgb.Put16(buf[b:], uint16(v.X)) + b += 2 + + xgb.Put16(buf[b:], uint16(v.Y)) + b += 2 + + return buf[:b] +} + +// TimecoordListBytes writes a list of Timecoord values to a byte slice. +func TimecoordListBytes(buf []byte, list []Timecoord) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +type Timestamp uint32 + +// UnmapNotify is the event number for a UnmapNotifyEvent. +const UnmapNotify = 18 + +type UnmapNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Event Window + Window Window + FromConfigure bool + // padding: 3 bytes +} + +// UnmapNotifyEventNew constructs a UnmapNotifyEvent value that implements xgb.Event from a byte slice. +func UnmapNotifyEventNew(buf []byte) xgb.Event { + v := UnmapNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Event = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + if buf[b] == 1 { + v.FromConfigure = true + } else { + v.FromConfigure = false + } + b += 1 + + b += 3 // padding + + return v +} + +// Bytes writes a UnmapNotifyEvent value to a byte slice. +func (v UnmapNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 18 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Event)) + b += 4 + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + if v.FromConfigure { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + b += 3 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the UnmapNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v UnmapNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of UnmapNotifyEvent. +func (v UnmapNotifyEvent) String() string { + fieldVals := make([]string, 0, 5) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Event: %d", v.Event)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("FromConfigure: %t", v.FromConfigure)) + return "UnmapNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[18] = UnmapNotifyEventNew +} + +// BadValue is the error number for a BadValue. +const BadValue = 2 + +type ValueError struct { + Sequence uint16 + NiceName string + BadValue uint32 + MinorOpcode uint16 + MajorOpcode byte + // padding: 1 bytes +} + +// ValueErrorNew constructs a ValueError value that implements xgb.Error from a byte slice. +func ValueErrorNew(buf []byte) xgb.Error { + v := ValueError{} + v.NiceName = "Value" + + b := 1 // skip error determinant + b += 1 // don't read error number + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.BadValue = xgb.Get32(buf[b:]) + b += 4 + + v.MinorOpcode = xgb.Get16(buf[b:]) + b += 2 + + v.MajorOpcode = buf[b] + b += 1 + + b += 1 // padding + + return v +} + +// SequenceId returns the sequence id attached to the BadValue error. +// This is mostly used internally. +func (err ValueError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadValue error. If no bad value exists, 0 is returned. +func (err ValueError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadValue error. + +func (err ValueError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadValue {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[2] = ValueErrorNew +} + +const ( + VisibilityUnobscured = 0 + VisibilityPartiallyObscured = 1 + VisibilityFullyObscured = 2 +) + +// VisibilityNotify is the event number for a VisibilityNotifyEvent. +const VisibilityNotify = 15 + +type VisibilityNotifyEvent struct { + Sequence uint16 + // padding: 1 bytes + Window Window + State byte + // padding: 3 bytes +} + +// VisibilityNotifyEventNew constructs a VisibilityNotifyEvent value that implements xgb.Event from a byte slice. +func VisibilityNotifyEventNew(buf []byte) xgb.Event { + v := VisibilityNotifyEvent{} + b := 1 // don't read event number + + b += 1 // padding + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Window = Window(xgb.Get32(buf[b:])) + b += 4 + + v.State = buf[b] + b += 1 + + b += 3 // padding + + return v +} + +// Bytes writes a VisibilityNotifyEvent value to a byte slice. +func (v VisibilityNotifyEvent) Bytes() []byte { + buf := make([]byte, 32) + b := 0 + + // write event number + buf[b] = 15 + b += 1 + + b += 1 // padding + + b += 2 // skip sequence number + + xgb.Put32(buf[b:], uint32(v.Window)) + b += 4 + + buf[b] = v.State + b += 1 + + b += 3 // padding + + return buf +} + +// SequenceId returns the sequence id attached to the VisibilityNotify event. +// Events without a sequence number (KeymapNotify) return 0. +// This is mostly used internally. +func (v VisibilityNotifyEvent) SequenceId() uint16 { + return v.Sequence +} + +// String is a rudimentary string representation of VisibilityNotifyEvent. +func (v VisibilityNotifyEvent) String() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("Window: %d", v.Window)) + fieldVals = append(fieldVals, xgb.Sprintf("State: %d", v.State)) + return "VisibilityNotify {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewEventFuncs[15] = VisibilityNotifyEventNew +} + +const ( + VisualClassStaticGray = 0 + VisualClassGrayScale = 1 + VisualClassStaticColor = 2 + VisualClassPseudoColor = 3 + VisualClassTrueColor = 4 + VisualClassDirectColor = 5 +) + +type VisualInfo struct { + VisualId Visualid + Class byte + BitsPerRgbValue byte + ColormapEntries uint16 + RedMask uint32 + GreenMask uint32 + BlueMask uint32 + // padding: 4 bytes +} + +// VisualInfoRead reads a byte slice into a VisualInfo value. +func VisualInfoRead(buf []byte, v *VisualInfo) int { + b := 0 + + v.VisualId = Visualid(xgb.Get32(buf[b:])) + b += 4 + + v.Class = buf[b] + b += 1 + + v.BitsPerRgbValue = buf[b] + b += 1 + + v.ColormapEntries = xgb.Get16(buf[b:]) + b += 2 + + v.RedMask = xgb.Get32(buf[b:]) + b += 4 + + v.GreenMask = xgb.Get32(buf[b:]) + b += 4 + + v.BlueMask = xgb.Get32(buf[b:]) + b += 4 + + b += 4 // padding + + return b +} + +// VisualInfoReadList reads a byte slice into a list of VisualInfo values. +func VisualInfoReadList(buf []byte, dest []VisualInfo) int { + b := 0 + for i := 0; i < len(dest); i++ { + dest[i] = VisualInfo{} + b += VisualInfoRead(buf[b:], &dest[i]) + } + return xgb.Pad(b) +} + +// Bytes writes a VisualInfo value to a byte slice. +func (v VisualInfo) Bytes() []byte { + buf := make([]byte, 24) + b := 0 + + xgb.Put32(buf[b:], uint32(v.VisualId)) + b += 4 + + buf[b] = v.Class + b += 1 + + buf[b] = v.BitsPerRgbValue + b += 1 + + xgb.Put16(buf[b:], v.ColormapEntries) + b += 2 + + xgb.Put32(buf[b:], v.RedMask) + b += 4 + + xgb.Put32(buf[b:], v.GreenMask) + b += 4 + + xgb.Put32(buf[b:], v.BlueMask) + b += 4 + + b += 4 // padding + + return buf[:b] +} + +// VisualInfoListBytes writes a list of VisualInfo values to a byte slice. +func VisualInfoListBytes(buf []byte, list []VisualInfo) int { + b := 0 + var structBytes []byte + for _, item := range list { + structBytes = item.Bytes() + copy(buf[b:], structBytes) + b += len(structBytes) + } + return xgb.Pad(b) +} + +type Visualid uint32 + +type Window uint32 + +func NewWindowId(c *xgb.Conn) (Window, error) { + id, err := c.NewId() + if err != nil { + return 0, err + } + return Window(id), nil +} + +// BadWindow is the error number for a BadWindow. +const BadWindow = 3 + +type WindowError ValueError + +// WindowErrorNew constructs a WindowError value that implements xgb.Error from a byte slice. +func WindowErrorNew(buf []byte) xgb.Error { + v := WindowError(ValueErrorNew(buf).(ValueError)) + v.NiceName = "Window" + return v +} + +// SequenceId returns the sequence id attached to the BadWindow error. +// This is mostly used internally. +func (err WindowError) SequenceId() uint16 { + return err.Sequence +} + +// BadId returns the 'BadValue' number if one exists for the BadWindow error. If no bad value exists, 0 is returned. +func (err WindowError) BadId() uint32 { + return err.BadValue +} + +// Error returns a rudimentary string representation of the BadWindow error. +func (err WindowError) Error() string { + fieldVals := make([]string, 0, 4) + fieldVals = append(fieldVals, "NiceName: "+err.NiceName) + fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", err.Sequence)) + fieldVals = append(fieldVals, xgb.Sprintf("BadValue: %d", err.BadValue)) + fieldVals = append(fieldVals, xgb.Sprintf("MinorOpcode: %d", err.MinorOpcode)) + fieldVals = append(fieldVals, xgb.Sprintf("MajorOpcode: %d", err.MajorOpcode)) + return "BadWindow {" + xgb.StringsJoin(fieldVals, ", ") + "}" +} + +func init() { + xgb.NewErrorFuncs[3] = WindowErrorNew +} + +const ( + WindowNone = 0 +) + +const ( + WindowClassCopyFromParent = 0 + WindowClassInputOutput = 1 + WindowClassInputOnly = 2 +) + +// 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' + +// AllocColorCookie is a cookie used only for AllocColor requests. +type AllocColorCookie struct { + *xgb.Cookie +} + +// AllocColor sends a checked request. +// If an error occurs, it will be returned with the reply by calling AllocColorCookie.Reply() +func AllocColor(c *xgb.Conn, Cmap Colormap, Red uint16, Green uint16, Blue uint16) AllocColorCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(allocColorRequest(c, Cmap, Red, Green, Blue), cookie) + return AllocColorCookie{cookie} +} + +// AllocColorUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func AllocColorUnchecked(c *xgb.Conn, Cmap Colormap, Red uint16, Green uint16, Blue uint16) AllocColorCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(allocColorRequest(c, Cmap, Red, Green, Blue), cookie) + return AllocColorCookie{cookie} +} + +// AllocColorReply represents the data returned from a AllocColor request. +type AllocColorReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + Red uint16 + Green uint16 + Blue uint16 + // padding: 2 bytes + Pixel uint32 +} + +// Reply blocks and returns the reply data for a AllocColor request. +func (cook AllocColorCookie) Reply() (*AllocColorReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return allocColorReply(buf), nil +} + +// allocColorReply reads a byte slice into a AllocColorReply value. +func allocColorReply(buf []byte) *AllocColorReply { + v := new(AllocColorReply) + 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.Red = xgb.Get16(buf[b:]) + b += 2 + + v.Green = xgb.Get16(buf[b:]) + b += 2 + + v.Blue = xgb.Get16(buf[b:]) + b += 2 + + b += 2 // padding + + v.Pixel = xgb.Get32(buf[b:]) + b += 4 + + return v +} + +// Write request to wire for AllocColor +// allocColorRequest writes a AllocColor request to a byte slice. +func allocColorRequest(c *xgb.Conn, Cmap Colormap, Red uint16, Green uint16, Blue uint16) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 84 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + xgb.Put16(buf[b:], Red) + b += 2 + + xgb.Put16(buf[b:], Green) + b += 2 + + xgb.Put16(buf[b:], Blue) + b += 2 + + b += 2 // padding + + return buf +} + +// AllocColorCellsCookie is a cookie used only for AllocColorCells requests. +type AllocColorCellsCookie struct { + *xgb.Cookie +} + +// AllocColorCells sends a checked request. +// If an error occurs, it will be returned with the reply by calling AllocColorCellsCookie.Reply() +func AllocColorCells(c *xgb.Conn, Contiguous bool, Cmap Colormap, Colors uint16, Planes uint16) AllocColorCellsCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(allocColorCellsRequest(c, Contiguous, Cmap, Colors, Planes), cookie) + return AllocColorCellsCookie{cookie} +} + +// AllocColorCellsUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func AllocColorCellsUnchecked(c *xgb.Conn, Contiguous bool, Cmap Colormap, Colors uint16, Planes uint16) AllocColorCellsCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(allocColorCellsRequest(c, Contiguous, Cmap, Colors, Planes), cookie) + return AllocColorCellsCookie{cookie} +} + +// AllocColorCellsReply represents the data returned from a AllocColorCells request. +type AllocColorCellsReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + PixelsLen uint16 + MasksLen uint16 + // padding: 20 bytes + Pixels []uint32 // size: xgb.Pad((int(PixelsLen) * 4)) + // alignment gap to multiple of 4 + Masks []uint32 // size: xgb.Pad((int(MasksLen) * 4)) +} + +// Reply blocks and returns the reply data for a AllocColorCells request. +func (cook AllocColorCellsCookie) Reply() (*AllocColorCellsReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return allocColorCellsReply(buf), nil +} + +// allocColorCellsReply reads a byte slice into a AllocColorCellsReply value. +func allocColorCellsReply(buf []byte) *AllocColorCellsReply { + v := new(AllocColorCellsReply) + 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.PixelsLen = xgb.Get16(buf[b:]) + b += 2 + + v.MasksLen = xgb.Get16(buf[b:]) + b += 2 + + b += 20 // padding + + v.Pixels = make([]uint32, v.PixelsLen) + for i := 0; i < int(v.PixelsLen); i++ { + v.Pixels[i] = xgb.Get32(buf[b:]) + b += 4 + } + + b = (b + 3) & ^3 // alignment gap + + v.Masks = make([]uint32, v.MasksLen) + for i := 0; i < int(v.MasksLen); i++ { + v.Masks[i] = xgb.Get32(buf[b:]) + b += 4 + } + + return v +} + +// Write request to wire for AllocColorCells +// allocColorCellsRequest writes a AllocColorCells request to a byte slice. +func allocColorCellsRequest(c *xgb.Conn, Contiguous bool, Cmap Colormap, Colors uint16, Planes uint16) []byte { + size := 12 + b := 0 + buf := make([]byte, size) + + buf[b] = 86 // request opcode + b += 1 + + if Contiguous { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + xgb.Put16(buf[b:], Colors) + b += 2 + + xgb.Put16(buf[b:], Planes) + b += 2 + + return buf +} + +// AllocColorPlanesCookie is a cookie used only for AllocColorPlanes requests. +type AllocColorPlanesCookie struct { + *xgb.Cookie +} + +// AllocColorPlanes sends a checked request. +// If an error occurs, it will be returned with the reply by calling AllocColorPlanesCookie.Reply() +func AllocColorPlanes(c *xgb.Conn, Contiguous bool, Cmap Colormap, Colors uint16, Reds uint16, Greens uint16, Blues uint16) AllocColorPlanesCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(allocColorPlanesRequest(c, Contiguous, Cmap, Colors, Reds, Greens, Blues), cookie) + return AllocColorPlanesCookie{cookie} +} + +// AllocColorPlanesUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func AllocColorPlanesUnchecked(c *xgb.Conn, Contiguous bool, Cmap Colormap, Colors uint16, Reds uint16, Greens uint16, Blues uint16) AllocColorPlanesCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(allocColorPlanesRequest(c, Contiguous, Cmap, Colors, Reds, Greens, Blues), cookie) + return AllocColorPlanesCookie{cookie} +} + +// AllocColorPlanesReply represents the data returned from a AllocColorPlanes request. +type AllocColorPlanesReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + PixelsLen uint16 + // padding: 2 bytes + RedMask uint32 + GreenMask uint32 + BlueMask uint32 + // padding: 8 bytes + Pixels []uint32 // size: xgb.Pad((int(PixelsLen) * 4)) +} + +// Reply blocks and returns the reply data for a AllocColorPlanes request. +func (cook AllocColorPlanesCookie) Reply() (*AllocColorPlanesReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return allocColorPlanesReply(buf), nil +} + +// allocColorPlanesReply reads a byte slice into a AllocColorPlanesReply value. +func allocColorPlanesReply(buf []byte) *AllocColorPlanesReply { + v := new(AllocColorPlanesReply) + 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.PixelsLen = xgb.Get16(buf[b:]) + b += 2 + + b += 2 // padding + + v.RedMask = xgb.Get32(buf[b:]) + b += 4 + + v.GreenMask = xgb.Get32(buf[b:]) + b += 4 + + v.BlueMask = xgb.Get32(buf[b:]) + b += 4 + + b += 8 // padding + + v.Pixels = make([]uint32, v.PixelsLen) + for i := 0; i < int(v.PixelsLen); i++ { + v.Pixels[i] = xgb.Get32(buf[b:]) + b += 4 + } + + return v +} + +// Write request to wire for AllocColorPlanes +// allocColorPlanesRequest writes a AllocColorPlanes request to a byte slice. +func allocColorPlanesRequest(c *xgb.Conn, Contiguous bool, Cmap Colormap, Colors uint16, Reds uint16, Greens uint16, Blues uint16) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 87 // request opcode + b += 1 + + if Contiguous { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + xgb.Put16(buf[b:], Colors) + b += 2 + + xgb.Put16(buf[b:], Reds) + b += 2 + + xgb.Put16(buf[b:], Greens) + b += 2 + + xgb.Put16(buf[b:], Blues) + b += 2 + + return buf +} + +// AllocNamedColorCookie is a cookie used only for AllocNamedColor requests. +type AllocNamedColorCookie struct { + *xgb.Cookie +} + +// AllocNamedColor sends a checked request. +// If an error occurs, it will be returned with the reply by calling AllocNamedColorCookie.Reply() +func AllocNamedColor(c *xgb.Conn, Cmap Colormap, NameLen uint16, Name string) AllocNamedColorCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(allocNamedColorRequest(c, Cmap, NameLen, Name), cookie) + return AllocNamedColorCookie{cookie} +} + +// AllocNamedColorUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func AllocNamedColorUnchecked(c *xgb.Conn, Cmap Colormap, NameLen uint16, Name string) AllocNamedColorCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(allocNamedColorRequest(c, Cmap, NameLen, Name), cookie) + return AllocNamedColorCookie{cookie} +} + +// AllocNamedColorReply represents the data returned from a AllocNamedColor request. +type AllocNamedColorReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + Pixel uint32 + ExactRed uint16 + ExactGreen uint16 + ExactBlue uint16 + VisualRed uint16 + VisualGreen uint16 + VisualBlue uint16 +} + +// Reply blocks and returns the reply data for a AllocNamedColor request. +func (cook AllocNamedColorCookie) Reply() (*AllocNamedColorReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return allocNamedColorReply(buf), nil +} + +// allocNamedColorReply reads a byte slice into a AllocNamedColorReply value. +func allocNamedColorReply(buf []byte) *AllocNamedColorReply { + v := new(AllocNamedColorReply) + 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.Pixel = xgb.Get32(buf[b:]) + b += 4 + + v.ExactRed = xgb.Get16(buf[b:]) + b += 2 + + v.ExactGreen = xgb.Get16(buf[b:]) + b += 2 + + v.ExactBlue = xgb.Get16(buf[b:]) + b += 2 + + v.VisualRed = xgb.Get16(buf[b:]) + b += 2 + + v.VisualGreen = xgb.Get16(buf[b:]) + b += 2 + + v.VisualBlue = xgb.Get16(buf[b:]) + b += 2 + + return v +} + +// Write request to wire for AllocNamedColor +// allocNamedColorRequest writes a AllocNamedColor request to a byte slice. +func allocNamedColorRequest(c *xgb.Conn, Cmap Colormap, NameLen uint16, Name string) []byte { + size := xgb.Pad((12 + xgb.Pad((int(NameLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 85 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + xgb.Put16(buf[b:], NameLen) + b += 2 + + b += 2 // padding + + copy(buf[b:], Name[:NameLen]) + b += int(NameLen) + + return buf +} + +// AllowEventsCookie is a cookie used only for AllowEvents requests. +type AllowEventsCookie struct { + *xgb.Cookie +} + +// AllowEvents sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func AllowEvents(c *xgb.Conn, Mode byte, Time Timestamp) AllowEventsCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(allowEventsRequest(c, Mode, Time), cookie) + return AllowEventsCookie{cookie} +} + +// AllowEventsChecked sends a checked request. +// If an error occurs, it can be retrieved using AllowEventsCookie.Check() +func AllowEventsChecked(c *xgb.Conn, Mode byte, Time Timestamp) AllowEventsCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(allowEventsRequest(c, Mode, Time), cookie) + return AllowEventsCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook AllowEventsCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for AllowEvents +// allowEventsRequest writes a AllowEvents request to a byte slice. +func allowEventsRequest(c *xgb.Conn, Mode byte, Time Timestamp) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 35 // request opcode + b += 1 + + buf[b] = Mode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Time)) + b += 4 + + return buf +} + +// BellCookie is a cookie used only for Bell requests. +type BellCookie struct { + *xgb.Cookie +} + +// Bell sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func Bell(c *xgb.Conn, Percent int8) BellCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(bellRequest(c, Percent), cookie) + return BellCookie{cookie} +} + +// BellChecked sends a checked request. +// If an error occurs, it can be retrieved using BellCookie.Check() +func BellChecked(c *xgb.Conn, Percent int8) BellCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(bellRequest(c, Percent), cookie) + return BellCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook BellCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for Bell +// bellRequest writes a Bell request to a byte slice. +func bellRequest(c *xgb.Conn, Percent int8) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 104 // request opcode + b += 1 + + buf[b] = byte(Percent) + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// ChangeActivePointerGrabCookie is a cookie used only for ChangeActivePointerGrab requests. +type ChangeActivePointerGrabCookie struct { + *xgb.Cookie +} + +// ChangeActivePointerGrab sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ChangeActivePointerGrab(c *xgb.Conn, Cursor Cursor, Time Timestamp, EventMask uint16) ChangeActivePointerGrabCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(changeActivePointerGrabRequest(c, Cursor, Time, EventMask), cookie) + return ChangeActivePointerGrabCookie{cookie} +} + +// ChangeActivePointerGrabChecked sends a checked request. +// If an error occurs, it can be retrieved using ChangeActivePointerGrabCookie.Check() +func ChangeActivePointerGrabChecked(c *xgb.Conn, Cursor Cursor, Time Timestamp, EventMask uint16) ChangeActivePointerGrabCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(changeActivePointerGrabRequest(c, Cursor, Time, EventMask), cookie) + return ChangeActivePointerGrabCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ChangeActivePointerGrabCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ChangeActivePointerGrab +// changeActivePointerGrabRequest writes a ChangeActivePointerGrab request to a byte slice. +func changeActivePointerGrabRequest(c *xgb.Conn, Cursor Cursor, Time Timestamp, EventMask uint16) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 30 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cursor)) + b += 4 + + xgb.Put32(buf[b:], uint32(Time)) + b += 4 + + xgb.Put16(buf[b:], EventMask) + b += 2 + + b += 2 // padding + + return buf +} + +// ChangeGCCookie is a cookie used only for ChangeGC requests. +type ChangeGCCookie struct { + *xgb.Cookie +} + +// ChangeGC sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ChangeGC(c *xgb.Conn, Gc Gcontext, ValueMask uint32, ValueList []uint32) ChangeGCCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(changeGCRequest(c, Gc, ValueMask, ValueList), cookie) + return ChangeGCCookie{cookie} +} + +// ChangeGCChecked sends a checked request. +// If an error occurs, it can be retrieved using ChangeGCCookie.Check() +func ChangeGCChecked(c *xgb.Conn, Gc Gcontext, ValueMask uint32, ValueList []uint32) ChangeGCCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(changeGCRequest(c, Gc, ValueMask, ValueList), cookie) + return ChangeGCCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ChangeGCCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ChangeGC +// changeGCRequest writes a ChangeGC request to a byte slice. +func changeGCRequest(c *xgb.Conn, Gc Gcontext, ValueMask uint32, ValueList []uint32) []byte { + size := xgb.Pad((8 + (4 + xgb.Pad((4 * xgb.PopCount(int(ValueMask))))))) + b := 0 + buf := make([]byte, size) + + buf[b] = 56 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + xgb.Put32(buf[b:], ValueMask) + b += 4 + for i := 0; i < xgb.PopCount(int(ValueMask)); i++ { + xgb.Put32(buf[b:], ValueList[i]) + b += 4 + } + b = xgb.Pad(b) + + return buf +} + +// ChangeHostsCookie is a cookie used only for ChangeHosts requests. +type ChangeHostsCookie struct { + *xgb.Cookie +} + +// ChangeHosts sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ChangeHosts(c *xgb.Conn, Mode byte, Family byte, AddressLen uint16, Address []byte) ChangeHostsCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(changeHostsRequest(c, Mode, Family, AddressLen, Address), cookie) + return ChangeHostsCookie{cookie} +} + +// ChangeHostsChecked sends a checked request. +// If an error occurs, it can be retrieved using ChangeHostsCookie.Check() +func ChangeHostsChecked(c *xgb.Conn, Mode byte, Family byte, AddressLen uint16, Address []byte) ChangeHostsCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(changeHostsRequest(c, Mode, Family, AddressLen, Address), cookie) + return ChangeHostsCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ChangeHostsCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ChangeHosts +// changeHostsRequest writes a ChangeHosts request to a byte slice. +func changeHostsRequest(c *xgb.Conn, Mode byte, Family byte, AddressLen uint16, Address []byte) []byte { + size := xgb.Pad((8 + xgb.Pad((int(AddressLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 109 // request opcode + b += 1 + + buf[b] = Mode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + buf[b] = Family + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], AddressLen) + b += 2 + + copy(buf[b:], Address[:AddressLen]) + b += int(AddressLen) + + return buf +} + +// ChangeKeyboardControlCookie is a cookie used only for ChangeKeyboardControl requests. +type ChangeKeyboardControlCookie struct { + *xgb.Cookie +} + +// ChangeKeyboardControl sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ChangeKeyboardControl(c *xgb.Conn, ValueMask uint32, ValueList []uint32) ChangeKeyboardControlCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(changeKeyboardControlRequest(c, ValueMask, ValueList), cookie) + return ChangeKeyboardControlCookie{cookie} +} + +// ChangeKeyboardControlChecked sends a checked request. +// If an error occurs, it can be retrieved using ChangeKeyboardControlCookie.Check() +func ChangeKeyboardControlChecked(c *xgb.Conn, ValueMask uint32, ValueList []uint32) ChangeKeyboardControlCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(changeKeyboardControlRequest(c, ValueMask, ValueList), cookie) + return ChangeKeyboardControlCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ChangeKeyboardControlCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ChangeKeyboardControl +// changeKeyboardControlRequest writes a ChangeKeyboardControl request to a byte slice. +func changeKeyboardControlRequest(c *xgb.Conn, ValueMask uint32, ValueList []uint32) []byte { + size := xgb.Pad((4 + (4 + xgb.Pad((4 * xgb.PopCount(int(ValueMask))))))) + b := 0 + buf := make([]byte, size) + + buf[b] = 102 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], ValueMask) + b += 4 + for i := 0; i < xgb.PopCount(int(ValueMask)); i++ { + xgb.Put32(buf[b:], ValueList[i]) + b += 4 + } + b = xgb.Pad(b) + + return buf +} + +// ChangeKeyboardMappingCookie is a cookie used only for ChangeKeyboardMapping requests. +type ChangeKeyboardMappingCookie struct { + *xgb.Cookie +} + +// ChangeKeyboardMapping sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ChangeKeyboardMapping(c *xgb.Conn, KeycodeCount byte, FirstKeycode Keycode, KeysymsPerKeycode byte, Keysyms []Keysym) ChangeKeyboardMappingCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(changeKeyboardMappingRequest(c, KeycodeCount, FirstKeycode, KeysymsPerKeycode, Keysyms), cookie) + return ChangeKeyboardMappingCookie{cookie} +} + +// ChangeKeyboardMappingChecked sends a checked request. +// If an error occurs, it can be retrieved using ChangeKeyboardMappingCookie.Check() +func ChangeKeyboardMappingChecked(c *xgb.Conn, KeycodeCount byte, FirstKeycode Keycode, KeysymsPerKeycode byte, Keysyms []Keysym) ChangeKeyboardMappingCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(changeKeyboardMappingRequest(c, KeycodeCount, FirstKeycode, KeysymsPerKeycode, Keysyms), cookie) + return ChangeKeyboardMappingCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ChangeKeyboardMappingCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ChangeKeyboardMapping +// changeKeyboardMappingRequest writes a ChangeKeyboardMapping request to a byte slice. +func changeKeyboardMappingRequest(c *xgb.Conn, KeycodeCount byte, FirstKeycode Keycode, KeysymsPerKeycode byte, Keysyms []Keysym) []byte { + size := xgb.Pad((8 + xgb.Pad(((int(KeycodeCount) * int(KeysymsPerKeycode)) * 4)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 100 // request opcode + b += 1 + + buf[b] = KeycodeCount + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + buf[b] = byte(FirstKeycode) + b += 1 + + buf[b] = KeysymsPerKeycode + b += 1 + + b += 2 // padding + + for i := 0; i < int((int(KeycodeCount) * int(KeysymsPerKeycode))); i++ { + xgb.Put32(buf[b:], uint32(Keysyms[i])) + b += 4 + } + + return buf +} + +// ChangePointerControlCookie is a cookie used only for ChangePointerControl requests. +type ChangePointerControlCookie struct { + *xgb.Cookie +} + +// ChangePointerControl sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ChangePointerControl(c *xgb.Conn, AccelerationNumerator int16, AccelerationDenominator int16, Threshold int16, DoAcceleration bool, DoThreshold bool) ChangePointerControlCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(changePointerControlRequest(c, AccelerationNumerator, AccelerationDenominator, Threshold, DoAcceleration, DoThreshold), cookie) + return ChangePointerControlCookie{cookie} +} + +// ChangePointerControlChecked sends a checked request. +// If an error occurs, it can be retrieved using ChangePointerControlCookie.Check() +func ChangePointerControlChecked(c *xgb.Conn, AccelerationNumerator int16, AccelerationDenominator int16, Threshold int16, DoAcceleration bool, DoThreshold bool) ChangePointerControlCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(changePointerControlRequest(c, AccelerationNumerator, AccelerationDenominator, Threshold, DoAcceleration, DoThreshold), cookie) + return ChangePointerControlCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ChangePointerControlCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ChangePointerControl +// changePointerControlRequest writes a ChangePointerControl request to a byte slice. +func changePointerControlRequest(c *xgb.Conn, AccelerationNumerator int16, AccelerationDenominator int16, Threshold int16, DoAcceleration bool, DoThreshold bool) []byte { + size := 12 + b := 0 + buf := make([]byte, size) + + buf[b] = 105 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put16(buf[b:], uint16(AccelerationNumerator)) + b += 2 + + xgb.Put16(buf[b:], uint16(AccelerationDenominator)) + b += 2 + + xgb.Put16(buf[b:], uint16(Threshold)) + b += 2 + + if DoAcceleration { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + if DoThreshold { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + return buf +} + +// ChangePropertyCookie is a cookie used only for ChangeProperty requests. +type ChangePropertyCookie struct { + *xgb.Cookie +} + +// ChangeProperty sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ChangeProperty(c *xgb.Conn, Mode byte, Window Window, Property Atom, Type Atom, Format byte, DataLen uint32, Data []byte) ChangePropertyCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(changePropertyRequest(c, Mode, Window, Property, Type, Format, DataLen, Data), cookie) + return ChangePropertyCookie{cookie} +} + +// ChangePropertyChecked sends a checked request. +// If an error occurs, it can be retrieved using ChangePropertyCookie.Check() +func ChangePropertyChecked(c *xgb.Conn, Mode byte, Window Window, Property Atom, Type Atom, Format byte, DataLen uint32, Data []byte) ChangePropertyCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(changePropertyRequest(c, Mode, Window, Property, Type, Format, DataLen, Data), cookie) + return ChangePropertyCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ChangePropertyCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ChangeProperty +// changePropertyRequest writes a ChangeProperty request to a byte slice. +func changePropertyRequest(c *xgb.Conn, Mode byte, Window Window, Property Atom, Type Atom, Format byte, DataLen uint32, Data []byte) []byte { + size := xgb.Pad((24 + xgb.Pad((((int(DataLen) * int(Format)) / 8) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 18 // request opcode + b += 1 + + buf[b] = Mode + 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:], uint32(Property)) + b += 4 + + xgb.Put32(buf[b:], uint32(Type)) + b += 4 + + buf[b] = Format + b += 1 + + b += 3 // padding + + xgb.Put32(buf[b:], DataLen) + b += 4 + + copy(buf[b:], Data[:((int(DataLen)*int(Format))/8)]) + b += int(((int(DataLen) * int(Format)) / 8)) + + return buf +} + +// ChangeSaveSetCookie is a cookie used only for ChangeSaveSet requests. +type ChangeSaveSetCookie struct { + *xgb.Cookie +} + +// ChangeSaveSet sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ChangeSaveSet(c *xgb.Conn, Mode byte, Window Window) ChangeSaveSetCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(changeSaveSetRequest(c, Mode, Window), cookie) + return ChangeSaveSetCookie{cookie} +} + +// ChangeSaveSetChecked sends a checked request. +// If an error occurs, it can be retrieved using ChangeSaveSetCookie.Check() +func ChangeSaveSetChecked(c *xgb.Conn, Mode byte, Window Window) ChangeSaveSetCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(changeSaveSetRequest(c, Mode, Window), cookie) + return ChangeSaveSetCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ChangeSaveSetCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ChangeSaveSet +// changeSaveSetRequest writes a ChangeSaveSet request to a byte slice. +func changeSaveSetRequest(c *xgb.Conn, Mode byte, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 6 // request opcode + b += 1 + + buf[b] = Mode + 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 +} + +// ChangeWindowAttributesCookie is a cookie used only for ChangeWindowAttributes requests. +type ChangeWindowAttributesCookie struct { + *xgb.Cookie +} + +// ChangeWindowAttributes sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ChangeWindowAttributes(c *xgb.Conn, Window Window, ValueMask uint32, ValueList []uint32) ChangeWindowAttributesCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(changeWindowAttributesRequest(c, Window, ValueMask, ValueList), cookie) + return ChangeWindowAttributesCookie{cookie} +} + +// ChangeWindowAttributesChecked sends a checked request. +// If an error occurs, it can be retrieved using ChangeWindowAttributesCookie.Check() +func ChangeWindowAttributesChecked(c *xgb.Conn, Window Window, ValueMask uint32, ValueList []uint32) ChangeWindowAttributesCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(changeWindowAttributesRequest(c, Window, ValueMask, ValueList), cookie) + return ChangeWindowAttributesCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ChangeWindowAttributesCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ChangeWindowAttributes +// changeWindowAttributesRequest writes a ChangeWindowAttributes request to a byte slice. +func changeWindowAttributesRequest(c *xgb.Conn, Window Window, ValueMask uint32, ValueList []uint32) []byte { + size := xgb.Pad((8 + (4 + xgb.Pad((4 * xgb.PopCount(int(ValueMask))))))) + b := 0 + buf := make([]byte, size) + + buf[b] = 2 // request opcode + b += 1 + + b += 1 // padding + + 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:], ValueMask) + b += 4 + for i := 0; i < xgb.PopCount(int(ValueMask)); i++ { + xgb.Put32(buf[b:], ValueList[i]) + b += 4 + } + b = xgb.Pad(b) + + return buf +} + +// CirculateWindowCookie is a cookie used only for CirculateWindow requests. +type CirculateWindowCookie struct { + *xgb.Cookie +} + +// CirculateWindow sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CirculateWindow(c *xgb.Conn, Direction byte, Window Window) CirculateWindowCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(circulateWindowRequest(c, Direction, Window), cookie) + return CirculateWindowCookie{cookie} +} + +// CirculateWindowChecked sends a checked request. +// If an error occurs, it can be retrieved using CirculateWindowCookie.Check() +func CirculateWindowChecked(c *xgb.Conn, Direction byte, Window Window) CirculateWindowCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(circulateWindowRequest(c, Direction, Window), cookie) + return CirculateWindowCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CirculateWindowCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CirculateWindow +// circulateWindowRequest writes a CirculateWindow request to a byte slice. +func circulateWindowRequest(c *xgb.Conn, Direction byte, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 13 // request opcode + b += 1 + + buf[b] = Direction + 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 +} + +// ClearAreaCookie is a cookie used only for ClearArea requests. +type ClearAreaCookie struct { + *xgb.Cookie +} + +// ClearArea sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ClearArea(c *xgb.Conn, Exposures bool, Window Window, X int16, Y int16, Width uint16, Height uint16) ClearAreaCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(clearAreaRequest(c, Exposures, Window, X, Y, Width, Height), cookie) + return ClearAreaCookie{cookie} +} + +// ClearAreaChecked sends a checked request. +// If an error occurs, it can be retrieved using ClearAreaCookie.Check() +func ClearAreaChecked(c *xgb.Conn, Exposures bool, Window Window, X int16, Y int16, Width uint16, Height uint16) ClearAreaCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(clearAreaRequest(c, Exposures, Window, X, Y, Width, Height), cookie) + return ClearAreaCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ClearAreaCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ClearArea +// clearAreaRequest writes a ClearArea request to a byte slice. +func clearAreaRequest(c *xgb.Conn, Exposures bool, Window Window, X int16, Y int16, Width uint16, Height uint16) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 61 // request opcode + b += 1 + + if Exposures { + buf[b] = 1 + } else { + buf[b] = 0 + } + 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.Put16(buf[b:], uint16(X)) + b += 2 + + xgb.Put16(buf[b:], uint16(Y)) + b += 2 + + xgb.Put16(buf[b:], Width) + b += 2 + + xgb.Put16(buf[b:], Height) + b += 2 + + return buf +} + +// CloseFontCookie is a cookie used only for CloseFont requests. +type CloseFontCookie struct { + *xgb.Cookie +} + +// CloseFont sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CloseFont(c *xgb.Conn, Font Font) CloseFontCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(closeFontRequest(c, Font), cookie) + return CloseFontCookie{cookie} +} + +// CloseFontChecked sends a checked request. +// If an error occurs, it can be retrieved using CloseFontCookie.Check() +func CloseFontChecked(c *xgb.Conn, Font Font) CloseFontCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(closeFontRequest(c, Font), cookie) + return CloseFontCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CloseFontCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CloseFont +// closeFontRequest writes a CloseFont request to a byte slice. +func closeFontRequest(c *xgb.Conn, Font Font) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 46 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Font)) + b += 4 + + return buf +} + +// ConfigureWindowCookie is a cookie used only for ConfigureWindow requests. +type ConfigureWindowCookie struct { + *xgb.Cookie +} + +// ConfigureWindow sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ConfigureWindow(c *xgb.Conn, Window Window, ValueMask uint16, ValueList []uint32) ConfigureWindowCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(configureWindowRequest(c, Window, ValueMask, ValueList), cookie) + return ConfigureWindowCookie{cookie} +} + +// ConfigureWindowChecked sends a checked request. +// If an error occurs, it can be retrieved using ConfigureWindowCookie.Check() +func ConfigureWindowChecked(c *xgb.Conn, Window Window, ValueMask uint16, ValueList []uint32) ConfigureWindowCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(configureWindowRequest(c, Window, ValueMask, ValueList), cookie) + return ConfigureWindowCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ConfigureWindowCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ConfigureWindow +// configureWindowRequest writes a ConfigureWindow request to a byte slice. +func configureWindowRequest(c *xgb.Conn, Window Window, ValueMask uint16, ValueList []uint32) []byte { + size := xgb.Pad((10 + (2 + xgb.Pad((4 * xgb.PopCount(int(ValueMask))))))) + b := 0 + buf := make([]byte, size) + + buf[b] = 12 // request opcode + b += 1 + + b += 1 // padding + + 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.Put16(buf[b:], ValueMask) + b += 2 + + b += 2 // padding + + for i := 0; i < xgb.PopCount(int(ValueMask)); i++ { + xgb.Put32(buf[b:], ValueList[i]) + b += 4 + } + b = xgb.Pad(b) + + return buf +} + +// ConvertSelectionCookie is a cookie used only for ConvertSelection requests. +type ConvertSelectionCookie struct { + *xgb.Cookie +} + +// ConvertSelection sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ConvertSelection(c *xgb.Conn, Requestor Window, Selection Atom, Target Atom, Property Atom, Time Timestamp) ConvertSelectionCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(convertSelectionRequest(c, Requestor, Selection, Target, Property, Time), cookie) + return ConvertSelectionCookie{cookie} +} + +// ConvertSelectionChecked sends a checked request. +// If an error occurs, it can be retrieved using ConvertSelectionCookie.Check() +func ConvertSelectionChecked(c *xgb.Conn, Requestor Window, Selection Atom, Target Atom, Property Atom, Time Timestamp) ConvertSelectionCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(convertSelectionRequest(c, Requestor, Selection, Target, Property, Time), cookie) + return ConvertSelectionCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ConvertSelectionCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ConvertSelection +// convertSelectionRequest writes a ConvertSelection request to a byte slice. +func convertSelectionRequest(c *xgb.Conn, Requestor Window, Selection Atom, Target Atom, Property Atom, Time Timestamp) []byte { + size := 24 + b := 0 + buf := make([]byte, size) + + buf[b] = 24 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Requestor)) + b += 4 + + xgb.Put32(buf[b:], uint32(Selection)) + b += 4 + + xgb.Put32(buf[b:], uint32(Target)) + b += 4 + + xgb.Put32(buf[b:], uint32(Property)) + b += 4 + + xgb.Put32(buf[b:], uint32(Time)) + b += 4 + + return buf +} + +// CopyAreaCookie is a cookie used only for CopyArea requests. +type CopyAreaCookie struct { + *xgb.Cookie +} + +// CopyArea sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CopyArea(c *xgb.Conn, SrcDrawable Drawable, DstDrawable Drawable, Gc Gcontext, SrcX int16, SrcY int16, DstX int16, DstY int16, Width uint16, Height uint16) CopyAreaCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(copyAreaRequest(c, SrcDrawable, DstDrawable, Gc, SrcX, SrcY, DstX, DstY, Width, Height), cookie) + return CopyAreaCookie{cookie} +} + +// CopyAreaChecked sends a checked request. +// If an error occurs, it can be retrieved using CopyAreaCookie.Check() +func CopyAreaChecked(c *xgb.Conn, SrcDrawable Drawable, DstDrawable Drawable, Gc Gcontext, SrcX int16, SrcY int16, DstX int16, DstY int16, Width uint16, Height uint16) CopyAreaCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(copyAreaRequest(c, SrcDrawable, DstDrawable, Gc, SrcX, SrcY, DstX, DstY, Width, Height), cookie) + return CopyAreaCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CopyAreaCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CopyArea +// copyAreaRequest writes a CopyArea request to a byte slice. +func copyAreaRequest(c *xgb.Conn, SrcDrawable Drawable, DstDrawable Drawable, Gc Gcontext, SrcX int16, SrcY int16, DstX int16, DstY int16, Width uint16, Height uint16) []byte { + size := 28 + b := 0 + buf := make([]byte, size) + + buf[b] = 62 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(SrcDrawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(DstDrawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + xgb.Put16(buf[b:], uint16(SrcX)) + b += 2 + + xgb.Put16(buf[b:], uint16(SrcY)) + b += 2 + + xgb.Put16(buf[b:], uint16(DstX)) + b += 2 + + xgb.Put16(buf[b:], uint16(DstY)) + b += 2 + + xgb.Put16(buf[b:], Width) + b += 2 + + xgb.Put16(buf[b:], Height) + b += 2 + + return buf +} + +// CopyColormapAndFreeCookie is a cookie used only for CopyColormapAndFree requests. +type CopyColormapAndFreeCookie struct { + *xgb.Cookie +} + +// CopyColormapAndFree sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CopyColormapAndFree(c *xgb.Conn, Mid Colormap, SrcCmap Colormap) CopyColormapAndFreeCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(copyColormapAndFreeRequest(c, Mid, SrcCmap), cookie) + return CopyColormapAndFreeCookie{cookie} +} + +// CopyColormapAndFreeChecked sends a checked request. +// If an error occurs, it can be retrieved using CopyColormapAndFreeCookie.Check() +func CopyColormapAndFreeChecked(c *xgb.Conn, Mid Colormap, SrcCmap Colormap) CopyColormapAndFreeCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(copyColormapAndFreeRequest(c, Mid, SrcCmap), cookie) + return CopyColormapAndFreeCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CopyColormapAndFreeCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CopyColormapAndFree +// copyColormapAndFreeRequest writes a CopyColormapAndFree request to a byte slice. +func copyColormapAndFreeRequest(c *xgb.Conn, Mid Colormap, SrcCmap Colormap) []byte { + size := 12 + b := 0 + buf := make([]byte, size) + + buf[b] = 80 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Mid)) + b += 4 + + xgb.Put32(buf[b:], uint32(SrcCmap)) + b += 4 + + return buf +} + +// CopyGCCookie is a cookie used only for CopyGC requests. +type CopyGCCookie struct { + *xgb.Cookie +} + +// CopyGC sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CopyGC(c *xgb.Conn, SrcGc Gcontext, DstGc Gcontext, ValueMask uint32) CopyGCCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(copyGCRequest(c, SrcGc, DstGc, ValueMask), cookie) + return CopyGCCookie{cookie} +} + +// CopyGCChecked sends a checked request. +// If an error occurs, it can be retrieved using CopyGCCookie.Check() +func CopyGCChecked(c *xgb.Conn, SrcGc Gcontext, DstGc Gcontext, ValueMask uint32) CopyGCCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(copyGCRequest(c, SrcGc, DstGc, ValueMask), cookie) + return CopyGCCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CopyGCCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CopyGC +// copyGCRequest writes a CopyGC request to a byte slice. +func copyGCRequest(c *xgb.Conn, SrcGc Gcontext, DstGc Gcontext, ValueMask uint32) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 57 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(SrcGc)) + b += 4 + + xgb.Put32(buf[b:], uint32(DstGc)) + b += 4 + + xgb.Put32(buf[b:], ValueMask) + b += 4 + + return buf +} + +// CopyPlaneCookie is a cookie used only for CopyPlane requests. +type CopyPlaneCookie struct { + *xgb.Cookie +} + +// CopyPlane sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CopyPlane(c *xgb.Conn, SrcDrawable Drawable, DstDrawable Drawable, Gc Gcontext, SrcX int16, SrcY int16, DstX int16, DstY int16, Width uint16, Height uint16, BitPlane uint32) CopyPlaneCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(copyPlaneRequest(c, SrcDrawable, DstDrawable, Gc, SrcX, SrcY, DstX, DstY, Width, Height, BitPlane), cookie) + return CopyPlaneCookie{cookie} +} + +// CopyPlaneChecked sends a checked request. +// If an error occurs, it can be retrieved using CopyPlaneCookie.Check() +func CopyPlaneChecked(c *xgb.Conn, SrcDrawable Drawable, DstDrawable Drawable, Gc Gcontext, SrcX int16, SrcY int16, DstX int16, DstY int16, Width uint16, Height uint16, BitPlane uint32) CopyPlaneCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(copyPlaneRequest(c, SrcDrawable, DstDrawable, Gc, SrcX, SrcY, DstX, DstY, Width, Height, BitPlane), cookie) + return CopyPlaneCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CopyPlaneCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CopyPlane +// copyPlaneRequest writes a CopyPlane request to a byte slice. +func copyPlaneRequest(c *xgb.Conn, SrcDrawable Drawable, DstDrawable Drawable, Gc Gcontext, SrcX int16, SrcY int16, DstX int16, DstY int16, Width uint16, Height uint16, BitPlane uint32) []byte { + size := 32 + b := 0 + buf := make([]byte, size) + + buf[b] = 63 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(SrcDrawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(DstDrawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + xgb.Put16(buf[b:], uint16(SrcX)) + b += 2 + + xgb.Put16(buf[b:], uint16(SrcY)) + b += 2 + + xgb.Put16(buf[b:], uint16(DstX)) + b += 2 + + xgb.Put16(buf[b:], uint16(DstY)) + b += 2 + + xgb.Put16(buf[b:], Width) + b += 2 + + xgb.Put16(buf[b:], Height) + b += 2 + + xgb.Put32(buf[b:], BitPlane) + b += 4 + + return buf +} + +// CreateColormapCookie is a cookie used only for CreateColormap requests. +type CreateColormapCookie struct { + *xgb.Cookie +} + +// CreateColormap sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CreateColormap(c *xgb.Conn, Alloc byte, Mid Colormap, Window Window, Visual Visualid) CreateColormapCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(createColormapRequest(c, Alloc, Mid, Window, Visual), cookie) + return CreateColormapCookie{cookie} +} + +// CreateColormapChecked sends a checked request. +// If an error occurs, it can be retrieved using CreateColormapCookie.Check() +func CreateColormapChecked(c *xgb.Conn, Alloc byte, Mid Colormap, Window Window, Visual Visualid) CreateColormapCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(createColormapRequest(c, Alloc, Mid, Window, Visual), cookie) + return CreateColormapCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CreateColormapCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CreateColormap +// createColormapRequest writes a CreateColormap request to a byte slice. +func createColormapRequest(c *xgb.Conn, Alloc byte, Mid Colormap, Window Window, Visual Visualid) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 78 // request opcode + b += 1 + + buf[b] = Alloc + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Mid)) + b += 4 + + xgb.Put32(buf[b:], uint32(Window)) + b += 4 + + xgb.Put32(buf[b:], uint32(Visual)) + b += 4 + + return buf +} + +// CreateCursorCookie is a cookie used only for CreateCursor requests. +type CreateCursorCookie struct { + *xgb.Cookie +} + +// CreateCursor sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CreateCursor(c *xgb.Conn, Cid Cursor, Source Pixmap, Mask Pixmap, ForeRed uint16, ForeGreen uint16, ForeBlue uint16, BackRed uint16, BackGreen uint16, BackBlue uint16, X uint16, Y uint16) CreateCursorCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(createCursorRequest(c, Cid, Source, Mask, ForeRed, ForeGreen, ForeBlue, BackRed, BackGreen, BackBlue, X, Y), cookie) + return CreateCursorCookie{cookie} +} + +// CreateCursorChecked sends a checked request. +// If an error occurs, it can be retrieved using CreateCursorCookie.Check() +func CreateCursorChecked(c *xgb.Conn, Cid Cursor, Source Pixmap, Mask Pixmap, ForeRed uint16, ForeGreen uint16, ForeBlue uint16, BackRed uint16, BackGreen uint16, BackBlue uint16, X uint16, Y uint16) CreateCursorCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(createCursorRequest(c, Cid, Source, Mask, ForeRed, ForeGreen, ForeBlue, BackRed, BackGreen, BackBlue, X, Y), cookie) + return CreateCursorCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CreateCursorCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CreateCursor +// createCursorRequest writes a CreateCursor request to a byte slice. +func createCursorRequest(c *xgb.Conn, Cid Cursor, Source Pixmap, Mask Pixmap, ForeRed uint16, ForeGreen uint16, ForeBlue uint16, BackRed uint16, BackGreen uint16, BackBlue uint16, X uint16, Y uint16) []byte { + size := 32 + b := 0 + buf := make([]byte, size) + + buf[b] = 93 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cid)) + b += 4 + + xgb.Put32(buf[b:], uint32(Source)) + b += 4 + + xgb.Put32(buf[b:], uint32(Mask)) + b += 4 + + xgb.Put16(buf[b:], ForeRed) + b += 2 + + xgb.Put16(buf[b:], ForeGreen) + b += 2 + + xgb.Put16(buf[b:], ForeBlue) + b += 2 + + xgb.Put16(buf[b:], BackRed) + b += 2 + + xgb.Put16(buf[b:], BackGreen) + b += 2 + + xgb.Put16(buf[b:], BackBlue) + b += 2 + + xgb.Put16(buf[b:], X) + b += 2 + + xgb.Put16(buf[b:], Y) + b += 2 + + return buf +} + +// CreateGCCookie is a cookie used only for CreateGC requests. +type CreateGCCookie struct { + *xgb.Cookie +} + +// CreateGC sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CreateGC(c *xgb.Conn, Cid Gcontext, Drawable Drawable, ValueMask uint32, ValueList []uint32) CreateGCCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(createGCRequest(c, Cid, Drawable, ValueMask, ValueList), cookie) + return CreateGCCookie{cookie} +} + +// CreateGCChecked sends a checked request. +// If an error occurs, it can be retrieved using CreateGCCookie.Check() +func CreateGCChecked(c *xgb.Conn, Cid Gcontext, Drawable Drawable, ValueMask uint32, ValueList []uint32) CreateGCCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(createGCRequest(c, Cid, Drawable, ValueMask, ValueList), cookie) + return CreateGCCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CreateGCCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CreateGC +// createGCRequest writes a CreateGC request to a byte slice. +func createGCRequest(c *xgb.Conn, Cid Gcontext, Drawable Drawable, ValueMask uint32, ValueList []uint32) []byte { + size := xgb.Pad((12 + (4 + xgb.Pad((4 * xgb.PopCount(int(ValueMask))))))) + b := 0 + buf := make([]byte, size) + + buf[b] = 55 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cid)) + b += 4 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], ValueMask) + b += 4 + for i := 0; i < xgb.PopCount(int(ValueMask)); i++ { + xgb.Put32(buf[b:], ValueList[i]) + b += 4 + } + b = xgb.Pad(b) + + return buf +} + +// CreateGlyphCursorCookie is a cookie used only for CreateGlyphCursor requests. +type CreateGlyphCursorCookie struct { + *xgb.Cookie +} + +// CreateGlyphCursor sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CreateGlyphCursor(c *xgb.Conn, Cid Cursor, SourceFont Font, MaskFont Font, SourceChar uint16, MaskChar uint16, ForeRed uint16, ForeGreen uint16, ForeBlue uint16, BackRed uint16, BackGreen uint16, BackBlue uint16) CreateGlyphCursorCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(createGlyphCursorRequest(c, Cid, SourceFont, MaskFont, SourceChar, MaskChar, ForeRed, ForeGreen, ForeBlue, BackRed, BackGreen, BackBlue), cookie) + return CreateGlyphCursorCookie{cookie} +} + +// CreateGlyphCursorChecked sends a checked request. +// If an error occurs, it can be retrieved using CreateGlyphCursorCookie.Check() +func CreateGlyphCursorChecked(c *xgb.Conn, Cid Cursor, SourceFont Font, MaskFont Font, SourceChar uint16, MaskChar uint16, ForeRed uint16, ForeGreen uint16, ForeBlue uint16, BackRed uint16, BackGreen uint16, BackBlue uint16) CreateGlyphCursorCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(createGlyphCursorRequest(c, Cid, SourceFont, MaskFont, SourceChar, MaskChar, ForeRed, ForeGreen, ForeBlue, BackRed, BackGreen, BackBlue), cookie) + return CreateGlyphCursorCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CreateGlyphCursorCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CreateGlyphCursor +// createGlyphCursorRequest writes a CreateGlyphCursor request to a byte slice. +func createGlyphCursorRequest(c *xgb.Conn, Cid Cursor, SourceFont Font, MaskFont Font, SourceChar uint16, MaskChar uint16, ForeRed uint16, ForeGreen uint16, ForeBlue uint16, BackRed uint16, BackGreen uint16, BackBlue uint16) []byte { + size := 32 + b := 0 + buf := make([]byte, size) + + buf[b] = 94 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cid)) + b += 4 + + xgb.Put32(buf[b:], uint32(SourceFont)) + b += 4 + + xgb.Put32(buf[b:], uint32(MaskFont)) + b += 4 + + xgb.Put16(buf[b:], SourceChar) + b += 2 + + xgb.Put16(buf[b:], MaskChar) + b += 2 + + xgb.Put16(buf[b:], ForeRed) + b += 2 + + xgb.Put16(buf[b:], ForeGreen) + b += 2 + + xgb.Put16(buf[b:], ForeBlue) + b += 2 + + xgb.Put16(buf[b:], BackRed) + b += 2 + + xgb.Put16(buf[b:], BackGreen) + b += 2 + + xgb.Put16(buf[b:], BackBlue) + b += 2 + + return buf +} + +// CreatePixmapCookie is a cookie used only for CreatePixmap requests. +type CreatePixmapCookie struct { + *xgb.Cookie +} + +// CreatePixmap sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CreatePixmap(c *xgb.Conn, Depth byte, Pid Pixmap, Drawable Drawable, Width uint16, Height uint16) CreatePixmapCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(createPixmapRequest(c, Depth, Pid, Drawable, Width, Height), cookie) + return CreatePixmapCookie{cookie} +} + +// CreatePixmapChecked sends a checked request. +// If an error occurs, it can be retrieved using CreatePixmapCookie.Check() +func CreatePixmapChecked(c *xgb.Conn, Depth byte, Pid Pixmap, Drawable Drawable, Width uint16, Height uint16) CreatePixmapCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(createPixmapRequest(c, Depth, Pid, Drawable, Width, Height), cookie) + return CreatePixmapCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CreatePixmapCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CreatePixmap +// createPixmapRequest writes a CreatePixmap request to a byte slice. +func createPixmapRequest(c *xgb.Conn, Depth byte, Pid Pixmap, Drawable Drawable, Width uint16, Height uint16) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 53 // request opcode + b += 1 + + buf[b] = Depth + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Pid)) + b += 4 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put16(buf[b:], Width) + b += 2 + + xgb.Put16(buf[b:], Height) + b += 2 + + return buf +} + +// CreateWindowCookie is a cookie used only for CreateWindow requests. +type CreateWindowCookie struct { + *xgb.Cookie +} + +// CreateWindow sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CreateWindow(c *xgb.Conn, Depth byte, Wid Window, Parent Window, X int16, Y int16, Width uint16, Height uint16, BorderWidth uint16, Class uint16, Visual Visualid, ValueMask uint32, ValueList []uint32) CreateWindowCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(createWindowRequest(c, Depth, Wid, Parent, X, Y, Width, Height, BorderWidth, Class, Visual, ValueMask, ValueList), cookie) + return CreateWindowCookie{cookie} +} + +// CreateWindowChecked sends a checked request. +// If an error occurs, it can be retrieved using CreateWindowCookie.Check() +func CreateWindowChecked(c *xgb.Conn, Depth byte, Wid Window, Parent Window, X int16, Y int16, Width uint16, Height uint16, BorderWidth uint16, Class uint16, Visual Visualid, ValueMask uint32, ValueList []uint32) CreateWindowCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(createWindowRequest(c, Depth, Wid, Parent, X, Y, Width, Height, BorderWidth, Class, Visual, ValueMask, ValueList), cookie) + return CreateWindowCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook CreateWindowCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for CreateWindow +// createWindowRequest writes a CreateWindow request to a byte slice. +func createWindowRequest(c *xgb.Conn, Depth byte, Wid Window, Parent Window, X int16, Y int16, Width uint16, Height uint16, BorderWidth uint16, Class uint16, Visual Visualid, ValueMask uint32, ValueList []uint32) []byte { + size := xgb.Pad((28 + (4 + xgb.Pad((4 * xgb.PopCount(int(ValueMask))))))) + b := 0 + buf := make([]byte, size) + + buf[b] = 1 // request opcode + b += 1 + + buf[b] = Depth + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Wid)) + b += 4 + + xgb.Put32(buf[b:], uint32(Parent)) + b += 4 + + xgb.Put16(buf[b:], uint16(X)) + b += 2 + + xgb.Put16(buf[b:], uint16(Y)) + b += 2 + + xgb.Put16(buf[b:], Width) + b += 2 + + xgb.Put16(buf[b:], Height) + b += 2 + + xgb.Put16(buf[b:], BorderWidth) + b += 2 + + xgb.Put16(buf[b:], Class) + b += 2 + + xgb.Put32(buf[b:], uint32(Visual)) + b += 4 + + xgb.Put32(buf[b:], ValueMask) + b += 4 + for i := 0; i < xgb.PopCount(int(ValueMask)); i++ { + xgb.Put32(buf[b:], ValueList[i]) + b += 4 + } + b = xgb.Pad(b) + + return buf +} + +// DeletePropertyCookie is a cookie used only for DeleteProperty requests. +type DeletePropertyCookie struct { + *xgb.Cookie +} + +// DeleteProperty sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func DeleteProperty(c *xgb.Conn, Window Window, Property Atom) DeletePropertyCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(deletePropertyRequest(c, Window, Property), cookie) + return DeletePropertyCookie{cookie} +} + +// DeletePropertyChecked sends a checked request. +// If an error occurs, it can be retrieved using DeletePropertyCookie.Check() +func DeletePropertyChecked(c *xgb.Conn, Window Window, Property Atom) DeletePropertyCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(deletePropertyRequest(c, Window, Property), cookie) + return DeletePropertyCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook DeletePropertyCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for DeleteProperty +// deletePropertyRequest writes a DeleteProperty request to a byte slice. +func deletePropertyRequest(c *xgb.Conn, Window Window, Property Atom) []byte { + size := 12 + b := 0 + buf := make([]byte, size) + + buf[b] = 19 // request opcode + b += 1 + + b += 1 // padding + + 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:], uint32(Property)) + b += 4 + + return buf +} + +// DestroySubwindowsCookie is a cookie used only for DestroySubwindows requests. +type DestroySubwindowsCookie struct { + *xgb.Cookie +} + +// DestroySubwindows sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func DestroySubwindows(c *xgb.Conn, Window Window) DestroySubwindowsCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(destroySubwindowsRequest(c, Window), cookie) + return DestroySubwindowsCookie{cookie} +} + +// DestroySubwindowsChecked sends a checked request. +// If an error occurs, it can be retrieved using DestroySubwindowsCookie.Check() +func DestroySubwindowsChecked(c *xgb.Conn, Window Window) DestroySubwindowsCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(destroySubwindowsRequest(c, Window), cookie) + return DestroySubwindowsCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook DestroySubwindowsCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for DestroySubwindows +// destroySubwindowsRequest writes a DestroySubwindows request to a byte slice. +func destroySubwindowsRequest(c *xgb.Conn, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 5 // request opcode + b += 1 + + b += 1 // padding + + 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 +} + +// DestroyWindowCookie is a cookie used only for DestroyWindow requests. +type DestroyWindowCookie struct { + *xgb.Cookie +} + +// DestroyWindow sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func DestroyWindow(c *xgb.Conn, Window Window) DestroyWindowCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(destroyWindowRequest(c, Window), cookie) + return DestroyWindowCookie{cookie} +} + +// DestroyWindowChecked sends a checked request. +// If an error occurs, it can be retrieved using DestroyWindowCookie.Check() +func DestroyWindowChecked(c *xgb.Conn, Window Window) DestroyWindowCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(destroyWindowRequest(c, Window), cookie) + return DestroyWindowCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook DestroyWindowCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for DestroyWindow +// destroyWindowRequest writes a DestroyWindow request to a byte slice. +func destroyWindowRequest(c *xgb.Conn, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 4 // request opcode + b += 1 + + b += 1 // padding + + 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 +} + +// FillPolyCookie is a cookie used only for FillPoly requests. +type FillPolyCookie struct { + *xgb.Cookie +} + +// FillPoly sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func FillPoly(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Shape byte, CoordinateMode byte, Points []Point) FillPolyCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(fillPolyRequest(c, Drawable, Gc, Shape, CoordinateMode, Points), cookie) + return FillPolyCookie{cookie} +} + +// FillPolyChecked sends a checked request. +// If an error occurs, it can be retrieved using FillPolyCookie.Check() +func FillPolyChecked(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Shape byte, CoordinateMode byte, Points []Point) FillPolyCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(fillPolyRequest(c, Drawable, Gc, Shape, CoordinateMode, Points), cookie) + return FillPolyCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook FillPolyCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for FillPoly +// fillPolyRequest writes a FillPoly request to a byte slice. +func fillPolyRequest(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Shape byte, CoordinateMode byte, Points []Point) []byte { + size := xgb.Pad((16 + xgb.Pad((len(Points) * 4)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 69 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + buf[b] = Shape + b += 1 + + buf[b] = CoordinateMode + b += 1 + + b += 2 // padding + + b += PointListBytes(buf[b:], Points) + + return buf +} + +// ForceScreenSaverCookie is a cookie used only for ForceScreenSaver requests. +type ForceScreenSaverCookie struct { + *xgb.Cookie +} + +// ForceScreenSaver sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ForceScreenSaver(c *xgb.Conn, Mode byte) ForceScreenSaverCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(forceScreenSaverRequest(c, Mode), cookie) + return ForceScreenSaverCookie{cookie} +} + +// ForceScreenSaverChecked sends a checked request. +// If an error occurs, it can be retrieved using ForceScreenSaverCookie.Check() +func ForceScreenSaverChecked(c *xgb.Conn, Mode byte) ForceScreenSaverCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(forceScreenSaverRequest(c, Mode), cookie) + return ForceScreenSaverCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ForceScreenSaverCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ForceScreenSaver +// forceScreenSaverRequest writes a ForceScreenSaver request to a byte slice. +func forceScreenSaverRequest(c *xgb.Conn, Mode byte) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 115 // request opcode + b += 1 + + buf[b] = Mode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// FreeColormapCookie is a cookie used only for FreeColormap requests. +type FreeColormapCookie struct { + *xgb.Cookie +} + +// FreeColormap sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func FreeColormap(c *xgb.Conn, Cmap Colormap) FreeColormapCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(freeColormapRequest(c, Cmap), cookie) + return FreeColormapCookie{cookie} +} + +// FreeColormapChecked sends a checked request. +// If an error occurs, it can be retrieved using FreeColormapCookie.Check() +func FreeColormapChecked(c *xgb.Conn, Cmap Colormap) FreeColormapCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(freeColormapRequest(c, Cmap), cookie) + return FreeColormapCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook FreeColormapCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for FreeColormap +// freeColormapRequest writes a FreeColormap request to a byte slice. +func freeColormapRequest(c *xgb.Conn, Cmap Colormap) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 79 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + return buf +} + +// FreeColorsCookie is a cookie used only for FreeColors requests. +type FreeColorsCookie struct { + *xgb.Cookie +} + +// FreeColors sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func FreeColors(c *xgb.Conn, Cmap Colormap, PlaneMask uint32, Pixels []uint32) FreeColorsCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(freeColorsRequest(c, Cmap, PlaneMask, Pixels), cookie) + return FreeColorsCookie{cookie} +} + +// FreeColorsChecked sends a checked request. +// If an error occurs, it can be retrieved using FreeColorsCookie.Check() +func FreeColorsChecked(c *xgb.Conn, Cmap Colormap, PlaneMask uint32, Pixels []uint32) FreeColorsCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(freeColorsRequest(c, Cmap, PlaneMask, Pixels), cookie) + return FreeColorsCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook FreeColorsCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for FreeColors +// freeColorsRequest writes a FreeColors request to a byte slice. +func freeColorsRequest(c *xgb.Conn, Cmap Colormap, PlaneMask uint32, Pixels []uint32) []byte { + size := xgb.Pad((12 + xgb.Pad((len(Pixels) * 4)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 88 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + xgb.Put32(buf[b:], PlaneMask) + b += 4 + + for i := 0; i < int(len(Pixels)); i++ { + xgb.Put32(buf[b:], Pixels[i]) + b += 4 + } + + return buf +} + +// FreeCursorCookie is a cookie used only for FreeCursor requests. +type FreeCursorCookie struct { + *xgb.Cookie +} + +// FreeCursor sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func FreeCursor(c *xgb.Conn, Cursor Cursor) FreeCursorCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(freeCursorRequest(c, Cursor), cookie) + return FreeCursorCookie{cookie} +} + +// FreeCursorChecked sends a checked request. +// If an error occurs, it can be retrieved using FreeCursorCookie.Check() +func FreeCursorChecked(c *xgb.Conn, Cursor Cursor) FreeCursorCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(freeCursorRequest(c, Cursor), cookie) + return FreeCursorCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook FreeCursorCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for FreeCursor +// freeCursorRequest writes a FreeCursor request to a byte slice. +func freeCursorRequest(c *xgb.Conn, Cursor Cursor) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 95 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cursor)) + b += 4 + + return buf +} + +// FreeGCCookie is a cookie used only for FreeGC requests. +type FreeGCCookie struct { + *xgb.Cookie +} + +// FreeGC sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func FreeGC(c *xgb.Conn, Gc Gcontext) FreeGCCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(freeGCRequest(c, Gc), cookie) + return FreeGCCookie{cookie} +} + +// FreeGCChecked sends a checked request. +// If an error occurs, it can be retrieved using FreeGCCookie.Check() +func FreeGCChecked(c *xgb.Conn, Gc Gcontext) FreeGCCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(freeGCRequest(c, Gc), cookie) + return FreeGCCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook FreeGCCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for FreeGC +// freeGCRequest writes a FreeGC request to a byte slice. +func freeGCRequest(c *xgb.Conn, Gc Gcontext) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 60 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + return buf +} + +// FreePixmapCookie is a cookie used only for FreePixmap requests. +type FreePixmapCookie struct { + *xgb.Cookie +} + +// FreePixmap sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func FreePixmap(c *xgb.Conn, Pixmap Pixmap) FreePixmapCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(freePixmapRequest(c, Pixmap), cookie) + return FreePixmapCookie{cookie} +} + +// FreePixmapChecked sends a checked request. +// If an error occurs, it can be retrieved using FreePixmapCookie.Check() +func FreePixmapChecked(c *xgb.Conn, Pixmap Pixmap) FreePixmapCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(freePixmapRequest(c, Pixmap), cookie) + return FreePixmapCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook FreePixmapCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for FreePixmap +// freePixmapRequest writes a FreePixmap request to a byte slice. +func freePixmapRequest(c *xgb.Conn, Pixmap Pixmap) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 54 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Pixmap)) + b += 4 + + return buf +} + +// GetAtomNameCookie is a cookie used only for GetAtomName requests. +type GetAtomNameCookie struct { + *xgb.Cookie +} + +// GetAtomName sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetAtomNameCookie.Reply() +func GetAtomName(c *xgb.Conn, Atom Atom) GetAtomNameCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getAtomNameRequest(c, Atom), cookie) + return GetAtomNameCookie{cookie} +} + +// GetAtomNameUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetAtomNameUnchecked(c *xgb.Conn, Atom Atom) GetAtomNameCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getAtomNameRequest(c, Atom), cookie) + return GetAtomNameCookie{cookie} +} + +// GetAtomNameReply represents the data returned from a GetAtomName request. +type GetAtomNameReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + NameLen uint16 + // padding: 22 bytes + Name string // size: xgb.Pad((int(NameLen) * 1)) +} + +// Reply blocks and returns the reply data for a GetAtomName request. +func (cook GetAtomNameCookie) Reply() (*GetAtomNameReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getAtomNameReply(buf), nil +} + +// getAtomNameReply reads a byte slice into a GetAtomNameReply value. +func getAtomNameReply(buf []byte) *GetAtomNameReply { + v := new(GetAtomNameReply) + 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.NameLen = xgb.Get16(buf[b:]) + b += 2 + + b += 22 // padding + + { + byteString := make([]byte, v.NameLen) + copy(byteString[:v.NameLen], buf[b:]) + v.Name = string(byteString) + b += int(v.NameLen) + } + + return v +} + +// Write request to wire for GetAtomName +// getAtomNameRequest writes a GetAtomName request to a byte slice. +func getAtomNameRequest(c *xgb.Conn, Atom Atom) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 17 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Atom)) + b += 4 + + return buf +} + +// GetFontPathCookie is a cookie used only for GetFontPath requests. +type GetFontPathCookie struct { + *xgb.Cookie +} + +// GetFontPath sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetFontPathCookie.Reply() +func GetFontPath(c *xgb.Conn) GetFontPathCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getFontPathRequest(c), cookie) + return GetFontPathCookie{cookie} +} + +// GetFontPathUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetFontPathUnchecked(c *xgb.Conn) GetFontPathCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getFontPathRequest(c), cookie) + return GetFontPathCookie{cookie} +} + +// GetFontPathReply represents the data returned from a GetFontPath request. +type GetFontPathReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + PathLen uint16 + // padding: 22 bytes + Path []Str // size: StrListSize(Path) +} + +// Reply blocks and returns the reply data for a GetFontPath request. +func (cook GetFontPathCookie) Reply() (*GetFontPathReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getFontPathReply(buf), nil +} + +// getFontPathReply reads a byte slice into a GetFontPathReply value. +func getFontPathReply(buf []byte) *GetFontPathReply { + v := new(GetFontPathReply) + 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.PathLen = xgb.Get16(buf[b:]) + b += 2 + + b += 22 // padding + + v.Path = make([]Str, v.PathLen) + b += StrReadList(buf[b:], v.Path) + + return v +} + +// Write request to wire for GetFontPath +// getFontPathRequest writes a GetFontPath request to a byte slice. +func getFontPathRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 52 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// GetGeometryCookie is a cookie used only for GetGeometry requests. +type GetGeometryCookie struct { + *xgb.Cookie +} + +// GetGeometry sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetGeometryCookie.Reply() +func GetGeometry(c *xgb.Conn, Drawable Drawable) GetGeometryCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getGeometryRequest(c, Drawable), cookie) + return GetGeometryCookie{cookie} +} + +// GetGeometryUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetGeometryUnchecked(c *xgb.Conn, Drawable Drawable) GetGeometryCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getGeometryRequest(c, Drawable), cookie) + return GetGeometryCookie{cookie} +} + +// GetGeometryReply represents the data returned from a GetGeometry request. +type GetGeometryReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Depth byte + Root Window + X int16 + Y int16 + Width uint16 + Height uint16 + BorderWidth uint16 + // padding: 2 bytes +} + +// Reply blocks and returns the reply data for a GetGeometry request. +func (cook GetGeometryCookie) Reply() (*GetGeometryReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getGeometryReply(buf), nil +} + +// getGeometryReply reads a byte slice into a GetGeometryReply value. +func getGeometryReply(buf []byte) *GetGeometryReply { + v := new(GetGeometryReply) + b := 1 // skip reply determinant + + v.Depth = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.Root = Window(xgb.Get32(buf[b:])) + b += 4 + + v.X = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Y = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Width = xgb.Get16(buf[b:]) + b += 2 + + v.Height = xgb.Get16(buf[b:]) + b += 2 + + v.BorderWidth = xgb.Get16(buf[b:]) + b += 2 + + b += 2 // padding + + return v +} + +// Write request to wire for GetGeometry +// getGeometryRequest writes a GetGeometry request to a byte slice. +func getGeometryRequest(c *xgb.Conn, Drawable Drawable) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 14 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + return buf +} + +// GetImageCookie is a cookie used only for GetImage requests. +type GetImageCookie struct { + *xgb.Cookie +} + +// GetImage sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetImageCookie.Reply() +func GetImage(c *xgb.Conn, Format byte, Drawable Drawable, X int16, Y int16, Width uint16, Height uint16, PlaneMask uint32) GetImageCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getImageRequest(c, Format, Drawable, X, Y, Width, Height, PlaneMask), cookie) + return GetImageCookie{cookie} +} + +// GetImageUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetImageUnchecked(c *xgb.Conn, Format byte, Drawable Drawable, X int16, Y int16, Width uint16, Height uint16, PlaneMask uint32) GetImageCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getImageRequest(c, Format, Drawable, X, Y, Width, Height, PlaneMask), cookie) + return GetImageCookie{cookie} +} + +// GetImageReply represents the data returned from a GetImage request. +type GetImageReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Depth byte + Visual Visualid + // padding: 20 bytes + Data []byte // size: xgb.Pad(((int(Length) * 4) * 1)) +} + +// Reply blocks and returns the reply data for a GetImage request. +func (cook GetImageCookie) Reply() (*GetImageReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getImageReply(buf), nil +} + +// getImageReply reads a byte slice into a GetImageReply value. +func getImageReply(buf []byte) *GetImageReply { + v := new(GetImageReply) + b := 1 // skip reply determinant + + v.Depth = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.Visual = Visualid(xgb.Get32(buf[b:])) + b += 4 + + b += 20 // padding + + v.Data = make([]byte, (int(v.Length) * 4)) + copy(v.Data[:(int(v.Length)*4)], buf[b:]) + b += int((int(v.Length) * 4)) + + return v +} + +// Write request to wire for GetImage +// getImageRequest writes a GetImage request to a byte slice. +func getImageRequest(c *xgb.Conn, Format byte, Drawable Drawable, X int16, Y int16, Width uint16, Height uint16, PlaneMask uint32) []byte { + size := 20 + b := 0 + buf := make([]byte, size) + + buf[b] = 73 // request opcode + b += 1 + + buf[b] = Format + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put16(buf[b:], uint16(X)) + b += 2 + + xgb.Put16(buf[b:], uint16(Y)) + b += 2 + + xgb.Put16(buf[b:], Width) + b += 2 + + xgb.Put16(buf[b:], Height) + b += 2 + + xgb.Put32(buf[b:], PlaneMask) + b += 4 + + return buf +} + +// GetInputFocusCookie is a cookie used only for GetInputFocus requests. +type GetInputFocusCookie struct { + *xgb.Cookie +} + +// GetInputFocus sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetInputFocusCookie.Reply() +func GetInputFocus(c *xgb.Conn) GetInputFocusCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getInputFocusRequest(c), cookie) + return GetInputFocusCookie{cookie} +} + +// GetInputFocusUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetInputFocusUnchecked(c *xgb.Conn) GetInputFocusCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getInputFocusRequest(c), cookie) + return GetInputFocusCookie{cookie} +} + +// GetInputFocusReply represents the data returned from a GetInputFocus request. +type GetInputFocusReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + RevertTo byte + Focus Window +} + +// Reply blocks and returns the reply data for a GetInputFocus request. +func (cook GetInputFocusCookie) Reply() (*GetInputFocusReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getInputFocusReply(buf), nil +} + +// getInputFocusReply reads a byte slice into a GetInputFocusReply value. +func getInputFocusReply(buf []byte) *GetInputFocusReply { + v := new(GetInputFocusReply) + b := 1 // skip reply determinant + + v.RevertTo = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.Focus = Window(xgb.Get32(buf[b:])) + b += 4 + + return v +} + +// Write request to wire for GetInputFocus +// getInputFocusRequest writes a GetInputFocus request to a byte slice. +func getInputFocusRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 43 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// GetKeyboardControlCookie is a cookie used only for GetKeyboardControl requests. +type GetKeyboardControlCookie struct { + *xgb.Cookie +} + +// GetKeyboardControl sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetKeyboardControlCookie.Reply() +func GetKeyboardControl(c *xgb.Conn) GetKeyboardControlCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getKeyboardControlRequest(c), cookie) + return GetKeyboardControlCookie{cookie} +} + +// GetKeyboardControlUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetKeyboardControlUnchecked(c *xgb.Conn) GetKeyboardControlCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getKeyboardControlRequest(c), cookie) + return GetKeyboardControlCookie{cookie} +} + +// GetKeyboardControlReply represents the data returned from a GetKeyboardControl request. +type GetKeyboardControlReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + GlobalAutoRepeat byte + LedMask uint32 + KeyClickPercent byte + BellPercent byte + BellPitch uint16 + BellDuration uint16 + // padding: 2 bytes + AutoRepeats []byte // size: 32 +} + +// Reply blocks and returns the reply data for a GetKeyboardControl request. +func (cook GetKeyboardControlCookie) Reply() (*GetKeyboardControlReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getKeyboardControlReply(buf), nil +} + +// getKeyboardControlReply reads a byte slice into a GetKeyboardControlReply value. +func getKeyboardControlReply(buf []byte) *GetKeyboardControlReply { + v := new(GetKeyboardControlReply) + b := 1 // skip reply determinant + + v.GlobalAutoRepeat = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.LedMask = xgb.Get32(buf[b:]) + b += 4 + + v.KeyClickPercent = buf[b] + b += 1 + + v.BellPercent = buf[b] + b += 1 + + v.BellPitch = xgb.Get16(buf[b:]) + b += 2 + + v.BellDuration = xgb.Get16(buf[b:]) + b += 2 + + b += 2 // padding + + v.AutoRepeats = make([]byte, 32) + copy(v.AutoRepeats[:32], buf[b:]) + b += int(32) + + return v +} + +// Write request to wire for GetKeyboardControl +// getKeyboardControlRequest writes a GetKeyboardControl request to a byte slice. +func getKeyboardControlRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 103 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// GetKeyboardMappingCookie is a cookie used only for GetKeyboardMapping requests. +type GetKeyboardMappingCookie struct { + *xgb.Cookie +} + +// GetKeyboardMapping sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetKeyboardMappingCookie.Reply() +func GetKeyboardMapping(c *xgb.Conn, FirstKeycode Keycode, Count byte) GetKeyboardMappingCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getKeyboardMappingRequest(c, FirstKeycode, Count), cookie) + return GetKeyboardMappingCookie{cookie} +} + +// GetKeyboardMappingUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetKeyboardMappingUnchecked(c *xgb.Conn, FirstKeycode Keycode, Count byte) GetKeyboardMappingCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getKeyboardMappingRequest(c, FirstKeycode, Count), cookie) + return GetKeyboardMappingCookie{cookie} +} + +// GetKeyboardMappingReply represents the data returned from a GetKeyboardMapping request. +type GetKeyboardMappingReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + KeysymsPerKeycode byte + // padding: 24 bytes + Keysyms []Keysym // size: xgb.Pad((int(Length) * 4)) +} + +// Reply blocks and returns the reply data for a GetKeyboardMapping request. +func (cook GetKeyboardMappingCookie) Reply() (*GetKeyboardMappingReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getKeyboardMappingReply(buf), nil +} + +// getKeyboardMappingReply reads a byte slice into a GetKeyboardMappingReply value. +func getKeyboardMappingReply(buf []byte) *GetKeyboardMappingReply { + v := new(GetKeyboardMappingReply) + b := 1 // skip reply determinant + + v.KeysymsPerKeycode = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + b += 24 // padding + + v.Keysyms = make([]Keysym, v.Length) + for i := 0; i < int(v.Length); i++ { + v.Keysyms[i] = Keysym(xgb.Get32(buf[b:])) + b += 4 + } + + return v +} + +// Write request to wire for GetKeyboardMapping +// getKeyboardMappingRequest writes a GetKeyboardMapping request to a byte slice. +func getKeyboardMappingRequest(c *xgb.Conn, FirstKeycode Keycode, Count byte) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 101 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + buf[b] = byte(FirstKeycode) + b += 1 + + buf[b] = Count + b += 1 + + return buf +} + +// GetModifierMappingCookie is a cookie used only for GetModifierMapping requests. +type GetModifierMappingCookie struct { + *xgb.Cookie +} + +// GetModifierMapping sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetModifierMappingCookie.Reply() +func GetModifierMapping(c *xgb.Conn) GetModifierMappingCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getModifierMappingRequest(c), cookie) + return GetModifierMappingCookie{cookie} +} + +// GetModifierMappingUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetModifierMappingUnchecked(c *xgb.Conn) GetModifierMappingCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getModifierMappingRequest(c), cookie) + return GetModifierMappingCookie{cookie} +} + +// GetModifierMappingReply represents the data returned from a GetModifierMapping request. +type GetModifierMappingReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + KeycodesPerModifier byte + // padding: 24 bytes + Keycodes []Keycode // size: xgb.Pad(((int(KeycodesPerModifier) * 8) * 1)) +} + +// Reply blocks and returns the reply data for a GetModifierMapping request. +func (cook GetModifierMappingCookie) Reply() (*GetModifierMappingReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getModifierMappingReply(buf), nil +} + +// getModifierMappingReply reads a byte slice into a GetModifierMappingReply value. +func getModifierMappingReply(buf []byte) *GetModifierMappingReply { + v := new(GetModifierMappingReply) + b := 1 // skip reply determinant + + v.KeycodesPerModifier = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + b += 24 // padding + + v.Keycodes = make([]Keycode, (int(v.KeycodesPerModifier) * 8)) + for i := 0; i < int((int(v.KeycodesPerModifier) * 8)); i++ { + v.Keycodes[i] = Keycode(buf[b]) + b += 1 + } + + return v +} + +// Write request to wire for GetModifierMapping +// getModifierMappingRequest writes a GetModifierMapping request to a byte slice. +func getModifierMappingRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 119 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// GetMotionEventsCookie is a cookie used only for GetMotionEvents requests. +type GetMotionEventsCookie struct { + *xgb.Cookie +} + +// GetMotionEvents sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetMotionEventsCookie.Reply() +func GetMotionEvents(c *xgb.Conn, Window Window, Start Timestamp, Stop Timestamp) GetMotionEventsCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getMotionEventsRequest(c, Window, Start, Stop), cookie) + return GetMotionEventsCookie{cookie} +} + +// GetMotionEventsUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetMotionEventsUnchecked(c *xgb.Conn, Window Window, Start Timestamp, Stop Timestamp) GetMotionEventsCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getMotionEventsRequest(c, Window, Start, Stop), cookie) + return GetMotionEventsCookie{cookie} +} + +// GetMotionEventsReply represents the data returned from a GetMotionEvents request. +type GetMotionEventsReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + EventsLen uint32 + // padding: 20 bytes + Events []Timecoord // size: xgb.Pad((int(EventsLen) * 8)) +} + +// Reply blocks and returns the reply data for a GetMotionEvents request. +func (cook GetMotionEventsCookie) Reply() (*GetMotionEventsReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getMotionEventsReply(buf), nil +} + +// getMotionEventsReply reads a byte slice into a GetMotionEventsReply value. +func getMotionEventsReply(buf []byte) *GetMotionEventsReply { + v := new(GetMotionEventsReply) + 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.EventsLen = xgb.Get32(buf[b:]) + b += 4 + + b += 20 // padding + + v.Events = make([]Timecoord, v.EventsLen) + b += TimecoordReadList(buf[b:], v.Events) + + return v +} + +// Write request to wire for GetMotionEvents +// getMotionEventsRequest writes a GetMotionEvents request to a byte slice. +func getMotionEventsRequest(c *xgb.Conn, Window Window, Start Timestamp, Stop Timestamp) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 39 // request opcode + b += 1 + + b += 1 // padding + + 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:], uint32(Start)) + b += 4 + + xgb.Put32(buf[b:], uint32(Stop)) + b += 4 + + return buf +} + +// GetPointerControlCookie is a cookie used only for GetPointerControl requests. +type GetPointerControlCookie struct { + *xgb.Cookie +} + +// GetPointerControl sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetPointerControlCookie.Reply() +func GetPointerControl(c *xgb.Conn) GetPointerControlCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getPointerControlRequest(c), cookie) + return GetPointerControlCookie{cookie} +} + +// GetPointerControlUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetPointerControlUnchecked(c *xgb.Conn) GetPointerControlCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getPointerControlRequest(c), cookie) + return GetPointerControlCookie{cookie} +} + +// GetPointerControlReply represents the data returned from a GetPointerControl request. +type GetPointerControlReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + AccelerationNumerator uint16 + AccelerationDenominator uint16 + Threshold uint16 + // padding: 18 bytes +} + +// Reply blocks and returns the reply data for a GetPointerControl request. +func (cook GetPointerControlCookie) Reply() (*GetPointerControlReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getPointerControlReply(buf), nil +} + +// getPointerControlReply reads a byte slice into a GetPointerControlReply value. +func getPointerControlReply(buf []byte) *GetPointerControlReply { + v := new(GetPointerControlReply) + 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.AccelerationNumerator = xgb.Get16(buf[b:]) + b += 2 + + v.AccelerationDenominator = xgb.Get16(buf[b:]) + b += 2 + + v.Threshold = xgb.Get16(buf[b:]) + b += 2 + + b += 18 // padding + + return v +} + +// Write request to wire for GetPointerControl +// getPointerControlRequest writes a GetPointerControl request to a byte slice. +func getPointerControlRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 106 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// GetPointerMappingCookie is a cookie used only for GetPointerMapping requests. +type GetPointerMappingCookie struct { + *xgb.Cookie +} + +// GetPointerMapping sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetPointerMappingCookie.Reply() +func GetPointerMapping(c *xgb.Conn) GetPointerMappingCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getPointerMappingRequest(c), cookie) + return GetPointerMappingCookie{cookie} +} + +// GetPointerMappingUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetPointerMappingUnchecked(c *xgb.Conn) GetPointerMappingCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getPointerMappingRequest(c), cookie) + return GetPointerMappingCookie{cookie} +} + +// GetPointerMappingReply represents the data returned from a GetPointerMapping request. +type GetPointerMappingReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + MapLen byte + // padding: 24 bytes + Map []byte // size: xgb.Pad((int(MapLen) * 1)) +} + +// Reply blocks and returns the reply data for a GetPointerMapping request. +func (cook GetPointerMappingCookie) Reply() (*GetPointerMappingReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getPointerMappingReply(buf), nil +} + +// getPointerMappingReply reads a byte slice into a GetPointerMappingReply value. +func getPointerMappingReply(buf []byte) *GetPointerMappingReply { + v := new(GetPointerMappingReply) + b := 1 // skip reply determinant + + v.MapLen = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + b += 24 // padding + + v.Map = make([]byte, v.MapLen) + copy(v.Map[:v.MapLen], buf[b:]) + b += int(v.MapLen) + + return v +} + +// Write request to wire for GetPointerMapping +// getPointerMappingRequest writes a GetPointerMapping request to a byte slice. +func getPointerMappingRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 117 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// GetPropertyCookie is a cookie used only for GetProperty requests. +type GetPropertyCookie struct { + *xgb.Cookie +} + +// GetProperty sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetPropertyCookie.Reply() +func GetProperty(c *xgb.Conn, Delete bool, Window Window, Property Atom, Type Atom, LongOffset uint32, LongLength uint32) GetPropertyCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getPropertyRequest(c, Delete, Window, Property, Type, LongOffset, LongLength), cookie) + return GetPropertyCookie{cookie} +} + +// GetPropertyUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetPropertyUnchecked(c *xgb.Conn, Delete bool, Window Window, Property Atom, Type Atom, LongOffset uint32, LongLength uint32) GetPropertyCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getPropertyRequest(c, Delete, Window, Property, Type, LongOffset, LongLength), cookie) + return GetPropertyCookie{cookie} +} + +// GetPropertyReply represents the data returned from a GetProperty request. +type GetPropertyReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Format byte + Type Atom + BytesAfter uint32 + ValueLen uint32 + // padding: 12 bytes + Value []byte // size: xgb.Pad(((int(ValueLen) * (int(Format) / 8)) * 1)) +} + +// Reply blocks and returns the reply data for a GetProperty request. +func (cook GetPropertyCookie) Reply() (*GetPropertyReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getPropertyReply(buf), nil +} + +// getPropertyReply reads a byte slice into a GetPropertyReply value. +func getPropertyReply(buf []byte) *GetPropertyReply { + v := new(GetPropertyReply) + b := 1 // skip reply determinant + + v.Format = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.Type = Atom(xgb.Get32(buf[b:])) + b += 4 + + v.BytesAfter = xgb.Get32(buf[b:]) + b += 4 + + v.ValueLen = xgb.Get32(buf[b:]) + b += 4 + + b += 12 // padding + + v.Value = make([]byte, (int(v.ValueLen) * (int(v.Format) / 8))) + copy(v.Value[:(int(v.ValueLen)*(int(v.Format)/8))], buf[b:]) + b += int((int(v.ValueLen) * (int(v.Format) / 8))) + + return v +} + +// Write request to wire for GetProperty +// getPropertyRequest writes a GetProperty request to a byte slice. +func getPropertyRequest(c *xgb.Conn, Delete bool, Window Window, Property Atom, Type Atom, LongOffset uint32, LongLength uint32) []byte { + size := 24 + b := 0 + buf := make([]byte, size) + + buf[b] = 20 // request opcode + b += 1 + + if Delete { + buf[b] = 1 + } else { + buf[b] = 0 + } + 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:], uint32(Property)) + b += 4 + + xgb.Put32(buf[b:], uint32(Type)) + b += 4 + + xgb.Put32(buf[b:], LongOffset) + b += 4 + + xgb.Put32(buf[b:], LongLength) + b += 4 + + return buf +} + +// GetScreenSaverCookie is a cookie used only for GetScreenSaver requests. +type GetScreenSaverCookie struct { + *xgb.Cookie +} + +// GetScreenSaver sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetScreenSaverCookie.Reply() +func GetScreenSaver(c *xgb.Conn) GetScreenSaverCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getScreenSaverRequest(c), cookie) + return GetScreenSaverCookie{cookie} +} + +// GetScreenSaverUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetScreenSaverUnchecked(c *xgb.Conn) GetScreenSaverCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getScreenSaverRequest(c), cookie) + return GetScreenSaverCookie{cookie} +} + +// GetScreenSaverReply represents the data returned from a GetScreenSaver request. +type GetScreenSaverReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + Timeout uint16 + Interval uint16 + PreferBlanking byte + AllowExposures byte + // padding: 18 bytes +} + +// Reply blocks and returns the reply data for a GetScreenSaver request. +func (cook GetScreenSaverCookie) Reply() (*GetScreenSaverReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getScreenSaverReply(buf), nil +} + +// getScreenSaverReply reads a byte slice into a GetScreenSaverReply value. +func getScreenSaverReply(buf []byte) *GetScreenSaverReply { + v := new(GetScreenSaverReply) + 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.Timeout = xgb.Get16(buf[b:]) + b += 2 + + v.Interval = xgb.Get16(buf[b:]) + b += 2 + + v.PreferBlanking = buf[b] + b += 1 + + v.AllowExposures = buf[b] + b += 1 + + b += 18 // padding + + return v +} + +// Write request to wire for GetScreenSaver +// getScreenSaverRequest writes a GetScreenSaver request to a byte slice. +func getScreenSaverRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 108 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// GetSelectionOwnerCookie is a cookie used only for GetSelectionOwner requests. +type GetSelectionOwnerCookie struct { + *xgb.Cookie +} + +// GetSelectionOwner sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetSelectionOwnerCookie.Reply() +func GetSelectionOwner(c *xgb.Conn, Selection Atom) GetSelectionOwnerCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getSelectionOwnerRequest(c, Selection), cookie) + return GetSelectionOwnerCookie{cookie} +} + +// GetSelectionOwnerUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetSelectionOwnerUnchecked(c *xgb.Conn, Selection Atom) GetSelectionOwnerCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getSelectionOwnerRequest(c, Selection), cookie) + return GetSelectionOwnerCookie{cookie} +} + +// GetSelectionOwnerReply represents the data returned from a GetSelectionOwner request. +type GetSelectionOwnerReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + Owner Window +} + +// Reply blocks and returns the reply data for a GetSelectionOwner request. +func (cook GetSelectionOwnerCookie) Reply() (*GetSelectionOwnerReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getSelectionOwnerReply(buf), nil +} + +// getSelectionOwnerReply reads a byte slice into a GetSelectionOwnerReply value. +func getSelectionOwnerReply(buf []byte) *GetSelectionOwnerReply { + v := new(GetSelectionOwnerReply) + 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.Owner = Window(xgb.Get32(buf[b:])) + b += 4 + + return v +} + +// Write request to wire for GetSelectionOwner +// getSelectionOwnerRequest writes a GetSelectionOwner request to a byte slice. +func getSelectionOwnerRequest(c *xgb.Conn, Selection Atom) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 23 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Selection)) + b += 4 + + return buf +} + +// GetWindowAttributesCookie is a cookie used only for GetWindowAttributes requests. +type GetWindowAttributesCookie struct { + *xgb.Cookie +} + +// GetWindowAttributes sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetWindowAttributesCookie.Reply() +func GetWindowAttributes(c *xgb.Conn, Window Window) GetWindowAttributesCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(getWindowAttributesRequest(c, Window), cookie) + return GetWindowAttributesCookie{cookie} +} + +// GetWindowAttributesUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetWindowAttributesUnchecked(c *xgb.Conn, Window Window) GetWindowAttributesCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(getWindowAttributesRequest(c, Window), cookie) + return GetWindowAttributesCookie{cookie} +} + +// GetWindowAttributesReply represents the data returned from a GetWindowAttributes request. +type GetWindowAttributesReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + BackingStore byte + Visual Visualid + Class uint16 + BitGravity byte + WinGravity byte + BackingPlanes uint32 + BackingPixel uint32 + SaveUnder bool + MapIsInstalled bool + MapState byte + OverrideRedirect bool + Colormap Colormap + AllEventMasks uint32 + YourEventMask uint32 + DoNotPropagateMask uint16 + // padding: 2 bytes +} + +// Reply blocks and returns the reply data for a GetWindowAttributes request. +func (cook GetWindowAttributesCookie) Reply() (*GetWindowAttributesReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getWindowAttributesReply(buf), nil +} + +// getWindowAttributesReply reads a byte slice into a GetWindowAttributesReply value. +func getWindowAttributesReply(buf []byte) *GetWindowAttributesReply { + v := new(GetWindowAttributesReply) + b := 1 // skip reply determinant + + v.BackingStore = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.Visual = Visualid(xgb.Get32(buf[b:])) + b += 4 + + v.Class = xgb.Get16(buf[b:]) + b += 2 + + v.BitGravity = buf[b] + b += 1 + + v.WinGravity = buf[b] + b += 1 + + v.BackingPlanes = xgb.Get32(buf[b:]) + b += 4 + + v.BackingPixel = xgb.Get32(buf[b:]) + b += 4 + + if buf[b] == 1 { + v.SaveUnder = true + } else { + v.SaveUnder = false + } + b += 1 + + if buf[b] == 1 { + v.MapIsInstalled = true + } else { + v.MapIsInstalled = false + } + b += 1 + + v.MapState = buf[b] + b += 1 + + if buf[b] == 1 { + v.OverrideRedirect = true + } else { + v.OverrideRedirect = false + } + b += 1 + + v.Colormap = Colormap(xgb.Get32(buf[b:])) + b += 4 + + v.AllEventMasks = xgb.Get32(buf[b:]) + b += 4 + + v.YourEventMask = xgb.Get32(buf[b:]) + b += 4 + + v.DoNotPropagateMask = xgb.Get16(buf[b:]) + b += 2 + + b += 2 // padding + + return v +} + +// Write request to wire for GetWindowAttributes +// getWindowAttributesRequest writes a GetWindowAttributes request to a byte slice. +func getWindowAttributesRequest(c *xgb.Conn, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 3 // request opcode + b += 1 + + b += 1 // padding + + 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 +} + +// GrabButtonCookie is a cookie used only for GrabButton requests. +type GrabButtonCookie struct { + *xgb.Cookie +} + +// GrabButton sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GrabButton(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, EventMask uint16, PointerMode byte, KeyboardMode byte, ConfineTo Window, Cursor Cursor, Button byte, Modifiers uint16) GrabButtonCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(grabButtonRequest(c, OwnerEvents, GrabWindow, EventMask, PointerMode, KeyboardMode, ConfineTo, Cursor, Button, Modifiers), cookie) + return GrabButtonCookie{cookie} +} + +// GrabButtonChecked sends a checked request. +// If an error occurs, it can be retrieved using GrabButtonCookie.Check() +func GrabButtonChecked(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, EventMask uint16, PointerMode byte, KeyboardMode byte, ConfineTo Window, Cursor Cursor, Button byte, Modifiers uint16) GrabButtonCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(grabButtonRequest(c, OwnerEvents, GrabWindow, EventMask, PointerMode, KeyboardMode, ConfineTo, Cursor, Button, Modifiers), cookie) + return GrabButtonCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook GrabButtonCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for GrabButton +// grabButtonRequest writes a GrabButton request to a byte slice. +func grabButtonRequest(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, EventMask uint16, PointerMode byte, KeyboardMode byte, ConfineTo Window, Cursor Cursor, Button byte, Modifiers uint16) []byte { + size := 24 + b := 0 + buf := make([]byte, size) + + buf[b] = 28 // request opcode + b += 1 + + if OwnerEvents { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(GrabWindow)) + b += 4 + + xgb.Put16(buf[b:], EventMask) + b += 2 + + buf[b] = PointerMode + b += 1 + + buf[b] = KeyboardMode + b += 1 + + xgb.Put32(buf[b:], uint32(ConfineTo)) + b += 4 + + xgb.Put32(buf[b:], uint32(Cursor)) + b += 4 + + buf[b] = Button + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], Modifiers) + b += 2 + + return buf +} + +// GrabKeyCookie is a cookie used only for GrabKey requests. +type GrabKeyCookie struct { + *xgb.Cookie +} + +// GrabKey sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GrabKey(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, Modifiers uint16, Key Keycode, PointerMode byte, KeyboardMode byte) GrabKeyCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(grabKeyRequest(c, OwnerEvents, GrabWindow, Modifiers, Key, PointerMode, KeyboardMode), cookie) + return GrabKeyCookie{cookie} +} + +// GrabKeyChecked sends a checked request. +// If an error occurs, it can be retrieved using GrabKeyCookie.Check() +func GrabKeyChecked(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, Modifiers uint16, Key Keycode, PointerMode byte, KeyboardMode byte) GrabKeyCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(grabKeyRequest(c, OwnerEvents, GrabWindow, Modifiers, Key, PointerMode, KeyboardMode), cookie) + return GrabKeyCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook GrabKeyCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for GrabKey +// grabKeyRequest writes a GrabKey request to a byte slice. +func grabKeyRequest(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, Modifiers uint16, Key Keycode, PointerMode byte, KeyboardMode byte) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 33 // request opcode + b += 1 + + if OwnerEvents { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(GrabWindow)) + b += 4 + + xgb.Put16(buf[b:], Modifiers) + b += 2 + + buf[b] = byte(Key) + b += 1 + + buf[b] = PointerMode + b += 1 + + buf[b] = KeyboardMode + b += 1 + + b += 3 // padding + + return buf +} + +// GrabKeyboardCookie is a cookie used only for GrabKeyboard requests. +type GrabKeyboardCookie struct { + *xgb.Cookie +} + +// GrabKeyboard sends a checked request. +// If an error occurs, it will be returned with the reply by calling GrabKeyboardCookie.Reply() +func GrabKeyboard(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, Time Timestamp, PointerMode byte, KeyboardMode byte) GrabKeyboardCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(grabKeyboardRequest(c, OwnerEvents, GrabWindow, Time, PointerMode, KeyboardMode), cookie) + return GrabKeyboardCookie{cookie} +} + +// GrabKeyboardUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GrabKeyboardUnchecked(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, Time Timestamp, PointerMode byte, KeyboardMode byte) GrabKeyboardCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(grabKeyboardRequest(c, OwnerEvents, GrabWindow, Time, PointerMode, KeyboardMode), cookie) + return GrabKeyboardCookie{cookie} +} + +// GrabKeyboardReply represents the data returned from a GrabKeyboard request. +type GrabKeyboardReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Status byte +} + +// Reply blocks and returns the reply data for a GrabKeyboard request. +func (cook GrabKeyboardCookie) Reply() (*GrabKeyboardReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return grabKeyboardReply(buf), nil +} + +// grabKeyboardReply reads a byte slice into a GrabKeyboardReply value. +func grabKeyboardReply(buf []byte) *GrabKeyboardReply { + v := new(GrabKeyboardReply) + b := 1 // skip reply determinant + + v.Status = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + return v +} + +// Write request to wire for GrabKeyboard +// grabKeyboardRequest writes a GrabKeyboard request to a byte slice. +func grabKeyboardRequest(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, Time Timestamp, PointerMode byte, KeyboardMode byte) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 31 // request opcode + b += 1 + + if OwnerEvents { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(GrabWindow)) + b += 4 + + xgb.Put32(buf[b:], uint32(Time)) + b += 4 + + buf[b] = PointerMode + b += 1 + + buf[b] = KeyboardMode + b += 1 + + b += 2 // padding + + return buf +} + +// GrabPointerCookie is a cookie used only for GrabPointer requests. +type GrabPointerCookie struct { + *xgb.Cookie +} + +// GrabPointer sends a checked request. +// If an error occurs, it will be returned with the reply by calling GrabPointerCookie.Reply() +func GrabPointer(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, EventMask uint16, PointerMode byte, KeyboardMode byte, ConfineTo Window, Cursor Cursor, Time Timestamp) GrabPointerCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(grabPointerRequest(c, OwnerEvents, GrabWindow, EventMask, PointerMode, KeyboardMode, ConfineTo, Cursor, Time), cookie) + return GrabPointerCookie{cookie} +} + +// GrabPointerUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GrabPointerUnchecked(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, EventMask uint16, PointerMode byte, KeyboardMode byte, ConfineTo Window, Cursor Cursor, Time Timestamp) GrabPointerCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(grabPointerRequest(c, OwnerEvents, GrabWindow, EventMask, PointerMode, KeyboardMode, ConfineTo, Cursor, Time), cookie) + return GrabPointerCookie{cookie} +} + +// GrabPointerReply represents the data returned from a GrabPointer request. +type GrabPointerReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Status byte +} + +// Reply blocks and returns the reply data for a GrabPointer request. +func (cook GrabPointerCookie) Reply() (*GrabPointerReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return grabPointerReply(buf), nil +} + +// grabPointerReply reads a byte slice into a GrabPointerReply value. +func grabPointerReply(buf []byte) *GrabPointerReply { + v := new(GrabPointerReply) + b := 1 // skip reply determinant + + v.Status = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + return v +} + +// Write request to wire for GrabPointer +// grabPointerRequest writes a GrabPointer request to a byte slice. +func grabPointerRequest(c *xgb.Conn, OwnerEvents bool, GrabWindow Window, EventMask uint16, PointerMode byte, KeyboardMode byte, ConfineTo Window, Cursor Cursor, Time Timestamp) []byte { + size := 24 + b := 0 + buf := make([]byte, size) + + buf[b] = 26 // request opcode + b += 1 + + if OwnerEvents { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(GrabWindow)) + b += 4 + + xgb.Put16(buf[b:], EventMask) + b += 2 + + buf[b] = PointerMode + b += 1 + + buf[b] = KeyboardMode + b += 1 + + xgb.Put32(buf[b:], uint32(ConfineTo)) + b += 4 + + xgb.Put32(buf[b:], uint32(Cursor)) + b += 4 + + xgb.Put32(buf[b:], uint32(Time)) + b += 4 + + return buf +} + +// GrabServerCookie is a cookie used only for GrabServer requests. +type GrabServerCookie struct { + *xgb.Cookie +} + +// GrabServer sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GrabServer(c *xgb.Conn) GrabServerCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(grabServerRequest(c), cookie) + return GrabServerCookie{cookie} +} + +// GrabServerChecked sends a checked request. +// If an error occurs, it can be retrieved using GrabServerCookie.Check() +func GrabServerChecked(c *xgb.Conn) GrabServerCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(grabServerRequest(c), cookie) + return GrabServerCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook GrabServerCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for GrabServer +// grabServerRequest writes a GrabServer request to a byte slice. +func grabServerRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 36 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// ImageText16Cookie is a cookie used only for ImageText16 requests. +type ImageText16Cookie struct { + *xgb.Cookie +} + +// ImageText16 sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ImageText16(c *xgb.Conn, StringLen byte, Drawable Drawable, Gc Gcontext, X int16, Y int16, String []Char2b) ImageText16Cookie { + cookie := c.NewCookie(false, false) + c.NewRequest(imageText16Request(c, StringLen, Drawable, Gc, X, Y, String), cookie) + return ImageText16Cookie{cookie} +} + +// ImageText16Checked sends a checked request. +// If an error occurs, it can be retrieved using ImageText16Cookie.Check() +func ImageText16Checked(c *xgb.Conn, StringLen byte, Drawable Drawable, Gc Gcontext, X int16, Y int16, String []Char2b) ImageText16Cookie { + cookie := c.NewCookie(true, false) + c.NewRequest(imageText16Request(c, StringLen, Drawable, Gc, X, Y, String), cookie) + return ImageText16Cookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ImageText16Cookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ImageText16 +// imageText16Request writes a ImageText16 request to a byte slice. +func imageText16Request(c *xgb.Conn, StringLen byte, Drawable Drawable, Gc Gcontext, X int16, Y int16, String []Char2b) []byte { + size := xgb.Pad((16 + xgb.Pad((int(StringLen) * 2)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 77 // request opcode + b += 1 + + buf[b] = StringLen + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + xgb.Put16(buf[b:], uint16(X)) + b += 2 + + xgb.Put16(buf[b:], uint16(Y)) + b += 2 + + b += Char2bListBytes(buf[b:], String) + + return buf +} + +// ImageText8Cookie is a cookie used only for ImageText8 requests. +type ImageText8Cookie struct { + *xgb.Cookie +} + +// ImageText8 sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ImageText8(c *xgb.Conn, StringLen byte, Drawable Drawable, Gc Gcontext, X int16, Y int16, String string) ImageText8Cookie { + cookie := c.NewCookie(false, false) + c.NewRequest(imageText8Request(c, StringLen, Drawable, Gc, X, Y, String), cookie) + return ImageText8Cookie{cookie} +} + +// ImageText8Checked sends a checked request. +// If an error occurs, it can be retrieved using ImageText8Cookie.Check() +func ImageText8Checked(c *xgb.Conn, StringLen byte, Drawable Drawable, Gc Gcontext, X int16, Y int16, String string) ImageText8Cookie { + cookie := c.NewCookie(true, false) + c.NewRequest(imageText8Request(c, StringLen, Drawable, Gc, X, Y, String), cookie) + return ImageText8Cookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ImageText8Cookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ImageText8 +// imageText8Request writes a ImageText8 request to a byte slice. +func imageText8Request(c *xgb.Conn, StringLen byte, Drawable Drawable, Gc Gcontext, X int16, Y int16, String string) []byte { + size := xgb.Pad((16 + xgb.Pad((int(StringLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 76 // request opcode + b += 1 + + buf[b] = StringLen + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + xgb.Put16(buf[b:], uint16(X)) + b += 2 + + xgb.Put16(buf[b:], uint16(Y)) + b += 2 + + copy(buf[b:], String[:StringLen]) + b += int(StringLen) + + return buf +} + +// InstallColormapCookie is a cookie used only for InstallColormap requests. +type InstallColormapCookie struct { + *xgb.Cookie +} + +// InstallColormap sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func InstallColormap(c *xgb.Conn, Cmap Colormap) InstallColormapCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(installColormapRequest(c, Cmap), cookie) + return InstallColormapCookie{cookie} +} + +// InstallColormapChecked sends a checked request. +// If an error occurs, it can be retrieved using InstallColormapCookie.Check() +func InstallColormapChecked(c *xgb.Conn, Cmap Colormap) InstallColormapCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(installColormapRequest(c, Cmap), cookie) + return InstallColormapCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook InstallColormapCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for InstallColormap +// installColormapRequest writes a InstallColormap request to a byte slice. +func installColormapRequest(c *xgb.Conn, Cmap Colormap) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 81 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + return buf +} + +// InternAtomCookie is a cookie used only for InternAtom requests. +type InternAtomCookie struct { + *xgb.Cookie +} + +// InternAtom sends a checked request. +// If an error occurs, it will be returned with the reply by calling InternAtomCookie.Reply() +func InternAtom(c *xgb.Conn, OnlyIfExists bool, NameLen uint16, Name string) InternAtomCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(internAtomRequest(c, OnlyIfExists, NameLen, Name), cookie) + return InternAtomCookie{cookie} +} + +// InternAtomUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func InternAtomUnchecked(c *xgb.Conn, OnlyIfExists bool, NameLen uint16, Name string) InternAtomCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(internAtomRequest(c, OnlyIfExists, NameLen, Name), cookie) + return InternAtomCookie{cookie} +} + +// InternAtomReply represents the data returned from a InternAtom request. +type InternAtomReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + Atom Atom +} + +// Reply blocks and returns the reply data for a InternAtom request. +func (cook InternAtomCookie) Reply() (*InternAtomReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return internAtomReply(buf), nil +} + +// internAtomReply reads a byte slice into a InternAtomReply value. +func internAtomReply(buf []byte) *InternAtomReply { + v := new(InternAtomReply) + 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.Atom = Atom(xgb.Get32(buf[b:])) + b += 4 + + return v +} + +// Write request to wire for InternAtom +// internAtomRequest writes a InternAtom request to a byte slice. +func internAtomRequest(c *xgb.Conn, OnlyIfExists bool, NameLen uint16, Name string) []byte { + size := xgb.Pad((8 + xgb.Pad((int(NameLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 16 // request opcode + b += 1 + + if OnlyIfExists { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put16(buf[b:], NameLen) + b += 2 + + b += 2 // padding + + copy(buf[b:], Name[:NameLen]) + b += int(NameLen) + + return buf +} + +// KillClientCookie is a cookie used only for KillClient requests. +type KillClientCookie struct { + *xgb.Cookie +} + +// KillClient sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func KillClient(c *xgb.Conn, Resource uint32) KillClientCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(killClientRequest(c, Resource), cookie) + return KillClientCookie{cookie} +} + +// KillClientChecked sends a checked request. +// If an error occurs, it can be retrieved using KillClientCookie.Check() +func KillClientChecked(c *xgb.Conn, Resource uint32) KillClientCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(killClientRequest(c, Resource), cookie) + return KillClientCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook KillClientCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for KillClient +// killClientRequest writes a KillClient request to a byte slice. +func killClientRequest(c *xgb.Conn, Resource uint32) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 113 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], Resource) + b += 4 + + return buf +} + +// ListExtensionsCookie is a cookie used only for ListExtensions requests. +type ListExtensionsCookie struct { + *xgb.Cookie +} + +// ListExtensions sends a checked request. +// If an error occurs, it will be returned with the reply by calling ListExtensionsCookie.Reply() +func ListExtensions(c *xgb.Conn) ListExtensionsCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(listExtensionsRequest(c), cookie) + return ListExtensionsCookie{cookie} +} + +// ListExtensionsUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ListExtensionsUnchecked(c *xgb.Conn) ListExtensionsCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(listExtensionsRequest(c), cookie) + return ListExtensionsCookie{cookie} +} + +// ListExtensionsReply represents the data returned from a ListExtensions request. +type ListExtensionsReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + NamesLen byte + // padding: 24 bytes + Names []Str // size: StrListSize(Names) +} + +// Reply blocks and returns the reply data for a ListExtensions request. +func (cook ListExtensionsCookie) Reply() (*ListExtensionsReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return listExtensionsReply(buf), nil +} + +// listExtensionsReply reads a byte slice into a ListExtensionsReply value. +func listExtensionsReply(buf []byte) *ListExtensionsReply { + v := new(ListExtensionsReply) + b := 1 // skip reply determinant + + v.NamesLen = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + b += 24 // padding + + v.Names = make([]Str, v.NamesLen) + b += StrReadList(buf[b:], v.Names) + + return v +} + +// Write request to wire for ListExtensions +// listExtensionsRequest writes a ListExtensions request to a byte slice. +func listExtensionsRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 99 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// ListFontsCookie is a cookie used only for ListFonts requests. +type ListFontsCookie struct { + *xgb.Cookie +} + +// ListFonts sends a checked request. +// If an error occurs, it will be returned with the reply by calling ListFontsCookie.Reply() +func ListFonts(c *xgb.Conn, MaxNames uint16, PatternLen uint16, Pattern string) ListFontsCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(listFontsRequest(c, MaxNames, PatternLen, Pattern), cookie) + return ListFontsCookie{cookie} +} + +// ListFontsUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ListFontsUnchecked(c *xgb.Conn, MaxNames uint16, PatternLen uint16, Pattern string) ListFontsCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(listFontsRequest(c, MaxNames, PatternLen, Pattern), cookie) + return ListFontsCookie{cookie} +} + +// ListFontsReply represents the data returned from a ListFonts request. +type ListFontsReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + NamesLen uint16 + // padding: 22 bytes + Names []Str // size: StrListSize(Names) +} + +// Reply blocks and returns the reply data for a ListFonts request. +func (cook ListFontsCookie) Reply() (*ListFontsReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return listFontsReply(buf), nil +} + +// listFontsReply reads a byte slice into a ListFontsReply value. +func listFontsReply(buf []byte) *ListFontsReply { + v := new(ListFontsReply) + 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.NamesLen = xgb.Get16(buf[b:]) + b += 2 + + b += 22 // padding + + v.Names = make([]Str, v.NamesLen) + b += StrReadList(buf[b:], v.Names) + + return v +} + +// Write request to wire for ListFonts +// listFontsRequest writes a ListFonts request to a byte slice. +func listFontsRequest(c *xgb.Conn, MaxNames uint16, PatternLen uint16, Pattern string) []byte { + size := xgb.Pad((8 + xgb.Pad((int(PatternLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 49 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put16(buf[b:], MaxNames) + b += 2 + + xgb.Put16(buf[b:], PatternLen) + b += 2 + + copy(buf[b:], Pattern[:PatternLen]) + b += int(PatternLen) + + return buf +} + +// ListFontsWithInfoCookie is a cookie used only for ListFontsWithInfo requests. +type ListFontsWithInfoCookie struct { + *xgb.Cookie +} + +// ListFontsWithInfo sends a checked request. +// If an error occurs, it will be returned with the reply by calling ListFontsWithInfoCookie.Reply() +func ListFontsWithInfo(c *xgb.Conn, MaxNames uint16, PatternLen uint16, Pattern string) ListFontsWithInfoCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(listFontsWithInfoRequest(c, MaxNames, PatternLen, Pattern), cookie) + return ListFontsWithInfoCookie{cookie} +} + +// ListFontsWithInfoUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ListFontsWithInfoUnchecked(c *xgb.Conn, MaxNames uint16, PatternLen uint16, Pattern string) ListFontsWithInfoCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(listFontsWithInfoRequest(c, MaxNames, PatternLen, Pattern), cookie) + return ListFontsWithInfoCookie{cookie} +} + +// ListFontsWithInfoReply represents the data returned from a ListFontsWithInfo request. +type ListFontsWithInfoReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + NameLen byte + MinBounds Charinfo + // padding: 4 bytes + MaxBounds Charinfo + // padding: 4 bytes + MinCharOrByte2 uint16 + MaxCharOrByte2 uint16 + DefaultChar uint16 + PropertiesLen uint16 + DrawDirection byte + MinByte1 byte + MaxByte1 byte + AllCharsExist bool + FontAscent int16 + FontDescent int16 + RepliesHint uint32 + Properties []Fontprop // size: xgb.Pad((int(PropertiesLen) * 8)) + Name string // size: xgb.Pad((int(NameLen) * 1)) +} + +// Reply blocks and returns the reply data for a ListFontsWithInfo request. +func (cook ListFontsWithInfoCookie) Reply() (*ListFontsWithInfoReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return listFontsWithInfoReply(buf), nil +} + +// listFontsWithInfoReply reads a byte slice into a ListFontsWithInfoReply value. +func listFontsWithInfoReply(buf []byte) *ListFontsWithInfoReply { + v := new(ListFontsWithInfoReply) + b := 1 // skip reply determinant + + v.NameLen = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.MinBounds = Charinfo{} + b += CharinfoRead(buf[b:], &v.MinBounds) + + b += 4 // padding + + v.MaxBounds = Charinfo{} + b += CharinfoRead(buf[b:], &v.MaxBounds) + + b += 4 // padding + + v.MinCharOrByte2 = xgb.Get16(buf[b:]) + b += 2 + + v.MaxCharOrByte2 = xgb.Get16(buf[b:]) + b += 2 + + v.DefaultChar = xgb.Get16(buf[b:]) + b += 2 + + v.PropertiesLen = xgb.Get16(buf[b:]) + b += 2 + + v.DrawDirection = buf[b] + b += 1 + + v.MinByte1 = buf[b] + b += 1 + + v.MaxByte1 = buf[b] + b += 1 + + if buf[b] == 1 { + v.AllCharsExist = true + } else { + v.AllCharsExist = false + } + b += 1 + + v.FontAscent = int16(xgb.Get16(buf[b:])) + b += 2 + + v.FontDescent = int16(xgb.Get16(buf[b:])) + b += 2 + + v.RepliesHint = xgb.Get32(buf[b:]) + b += 4 + + v.Properties = make([]Fontprop, v.PropertiesLen) + b += FontpropReadList(buf[b:], v.Properties) + + { + byteString := make([]byte, v.NameLen) + copy(byteString[:v.NameLen], buf[b:]) + v.Name = string(byteString) + b += int(v.NameLen) + } + + return v +} + +// Write request to wire for ListFontsWithInfo +// listFontsWithInfoRequest writes a ListFontsWithInfo request to a byte slice. +func listFontsWithInfoRequest(c *xgb.Conn, MaxNames uint16, PatternLen uint16, Pattern string) []byte { + size := xgb.Pad((8 + xgb.Pad((int(PatternLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 50 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put16(buf[b:], MaxNames) + b += 2 + + xgb.Put16(buf[b:], PatternLen) + b += 2 + + copy(buf[b:], Pattern[:PatternLen]) + b += int(PatternLen) + + return buf +} + +// ListHostsCookie is a cookie used only for ListHosts requests. +type ListHostsCookie struct { + *xgb.Cookie +} + +// ListHosts sends a checked request. +// If an error occurs, it will be returned with the reply by calling ListHostsCookie.Reply() +func ListHosts(c *xgb.Conn) ListHostsCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(listHostsRequest(c), cookie) + return ListHostsCookie{cookie} +} + +// ListHostsUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ListHostsUnchecked(c *xgb.Conn) ListHostsCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(listHostsRequest(c), cookie) + return ListHostsCookie{cookie} +} + +// ListHostsReply represents the data returned from a ListHosts request. +type ListHostsReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Mode byte + HostsLen uint16 + // padding: 22 bytes + Hosts []Host // size: HostListSize(Hosts) +} + +// Reply blocks and returns the reply data for a ListHosts request. +func (cook ListHostsCookie) Reply() (*ListHostsReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return listHostsReply(buf), nil +} + +// listHostsReply reads a byte slice into a ListHostsReply value. +func listHostsReply(buf []byte) *ListHostsReply { + v := new(ListHostsReply) + b := 1 // skip reply determinant + + v.Mode = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.HostsLen = xgb.Get16(buf[b:]) + b += 2 + + b += 22 // padding + + v.Hosts = make([]Host, v.HostsLen) + b += HostReadList(buf[b:], v.Hosts) + + return v +} + +// Write request to wire for ListHosts +// listHostsRequest writes a ListHosts request to a byte slice. +func listHostsRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 110 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// ListInstalledColormapsCookie is a cookie used only for ListInstalledColormaps requests. +type ListInstalledColormapsCookie struct { + *xgb.Cookie +} + +// ListInstalledColormaps sends a checked request. +// If an error occurs, it will be returned with the reply by calling ListInstalledColormapsCookie.Reply() +func ListInstalledColormaps(c *xgb.Conn, Window Window) ListInstalledColormapsCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(listInstalledColormapsRequest(c, Window), cookie) + return ListInstalledColormapsCookie{cookie} +} + +// ListInstalledColormapsUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ListInstalledColormapsUnchecked(c *xgb.Conn, Window Window) ListInstalledColormapsCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(listInstalledColormapsRequest(c, Window), cookie) + return ListInstalledColormapsCookie{cookie} +} + +// ListInstalledColormapsReply represents the data returned from a ListInstalledColormaps request. +type ListInstalledColormapsReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + CmapsLen uint16 + // padding: 22 bytes + Cmaps []Colormap // size: xgb.Pad((int(CmapsLen) * 4)) +} + +// Reply blocks and returns the reply data for a ListInstalledColormaps request. +func (cook ListInstalledColormapsCookie) Reply() (*ListInstalledColormapsReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return listInstalledColormapsReply(buf), nil +} + +// listInstalledColormapsReply reads a byte slice into a ListInstalledColormapsReply value. +func listInstalledColormapsReply(buf []byte) *ListInstalledColormapsReply { + v := new(ListInstalledColormapsReply) + 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.CmapsLen = xgb.Get16(buf[b:]) + b += 2 + + b += 22 // padding + + v.Cmaps = make([]Colormap, v.CmapsLen) + for i := 0; i < int(v.CmapsLen); i++ { + v.Cmaps[i] = Colormap(xgb.Get32(buf[b:])) + b += 4 + } + + return v +} + +// Write request to wire for ListInstalledColormaps +// listInstalledColormapsRequest writes a ListInstalledColormaps request to a byte slice. +func listInstalledColormapsRequest(c *xgb.Conn, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 83 // request opcode + b += 1 + + b += 1 // padding + + 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 +} + +// ListPropertiesCookie is a cookie used only for ListProperties requests. +type ListPropertiesCookie struct { + *xgb.Cookie +} + +// ListProperties sends a checked request. +// If an error occurs, it will be returned with the reply by calling ListPropertiesCookie.Reply() +func ListProperties(c *xgb.Conn, Window Window) ListPropertiesCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(listPropertiesRequest(c, Window), cookie) + return ListPropertiesCookie{cookie} +} + +// ListPropertiesUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ListPropertiesUnchecked(c *xgb.Conn, Window Window) ListPropertiesCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(listPropertiesRequest(c, Window), cookie) + return ListPropertiesCookie{cookie} +} + +// ListPropertiesReply represents the data returned from a ListProperties request. +type ListPropertiesReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + AtomsLen uint16 + // padding: 22 bytes + Atoms []Atom // size: xgb.Pad((int(AtomsLen) * 4)) +} + +// Reply blocks and returns the reply data for a ListProperties request. +func (cook ListPropertiesCookie) Reply() (*ListPropertiesReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return listPropertiesReply(buf), nil +} + +// listPropertiesReply reads a byte slice into a ListPropertiesReply value. +func listPropertiesReply(buf []byte) *ListPropertiesReply { + v := new(ListPropertiesReply) + 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.AtomsLen = xgb.Get16(buf[b:]) + b += 2 + + b += 22 // padding + + v.Atoms = make([]Atom, v.AtomsLen) + for i := 0; i < int(v.AtomsLen); i++ { + v.Atoms[i] = Atom(xgb.Get32(buf[b:])) + b += 4 + } + + return v +} + +// Write request to wire for ListProperties +// listPropertiesRequest writes a ListProperties request to a byte slice. +func listPropertiesRequest(c *xgb.Conn, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 21 // request opcode + b += 1 + + b += 1 // padding + + 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 +} + +// LookupColorCookie is a cookie used only for LookupColor requests. +type LookupColorCookie struct { + *xgb.Cookie +} + +// LookupColor sends a checked request. +// If an error occurs, it will be returned with the reply by calling LookupColorCookie.Reply() +func LookupColor(c *xgb.Conn, Cmap Colormap, NameLen uint16, Name string) LookupColorCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(lookupColorRequest(c, Cmap, NameLen, Name), cookie) + return LookupColorCookie{cookie} +} + +// LookupColorUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func LookupColorUnchecked(c *xgb.Conn, Cmap Colormap, NameLen uint16, Name string) LookupColorCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(lookupColorRequest(c, Cmap, NameLen, Name), cookie) + return LookupColorCookie{cookie} +} + +// LookupColorReply represents the data returned from a LookupColor request. +type LookupColorReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + ExactRed uint16 + ExactGreen uint16 + ExactBlue uint16 + VisualRed uint16 + VisualGreen uint16 + VisualBlue uint16 +} + +// Reply blocks and returns the reply data for a LookupColor request. +func (cook LookupColorCookie) Reply() (*LookupColorReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return lookupColorReply(buf), nil +} + +// lookupColorReply reads a byte slice into a LookupColorReply value. +func lookupColorReply(buf []byte) *LookupColorReply { + v := new(LookupColorReply) + 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.ExactRed = xgb.Get16(buf[b:]) + b += 2 + + v.ExactGreen = xgb.Get16(buf[b:]) + b += 2 + + v.ExactBlue = xgb.Get16(buf[b:]) + b += 2 + + v.VisualRed = xgb.Get16(buf[b:]) + b += 2 + + v.VisualGreen = xgb.Get16(buf[b:]) + b += 2 + + v.VisualBlue = xgb.Get16(buf[b:]) + b += 2 + + return v +} + +// Write request to wire for LookupColor +// lookupColorRequest writes a LookupColor request to a byte slice. +func lookupColorRequest(c *xgb.Conn, Cmap Colormap, NameLen uint16, Name string) []byte { + size := xgb.Pad((12 + xgb.Pad((int(NameLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 92 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + xgb.Put16(buf[b:], NameLen) + b += 2 + + b += 2 // padding + + copy(buf[b:], Name[:NameLen]) + b += int(NameLen) + + return buf +} + +// MapSubwindowsCookie is a cookie used only for MapSubwindows requests. +type MapSubwindowsCookie struct { + *xgb.Cookie +} + +// MapSubwindows sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func MapSubwindows(c *xgb.Conn, Window Window) MapSubwindowsCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(mapSubwindowsRequest(c, Window), cookie) + return MapSubwindowsCookie{cookie} +} + +// MapSubwindowsChecked sends a checked request. +// If an error occurs, it can be retrieved using MapSubwindowsCookie.Check() +func MapSubwindowsChecked(c *xgb.Conn, Window Window) MapSubwindowsCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(mapSubwindowsRequest(c, Window), cookie) + return MapSubwindowsCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook MapSubwindowsCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for MapSubwindows +// mapSubwindowsRequest writes a MapSubwindows request to a byte slice. +func mapSubwindowsRequest(c *xgb.Conn, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 9 // request opcode + b += 1 + + b += 1 // padding + + 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 +} + +// MapWindowCookie is a cookie used only for MapWindow requests. +type MapWindowCookie struct { + *xgb.Cookie +} + +// MapWindow sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func MapWindow(c *xgb.Conn, Window Window) MapWindowCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(mapWindowRequest(c, Window), cookie) + return MapWindowCookie{cookie} +} + +// MapWindowChecked sends a checked request. +// If an error occurs, it can be retrieved using MapWindowCookie.Check() +func MapWindowChecked(c *xgb.Conn, Window Window) MapWindowCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(mapWindowRequest(c, Window), cookie) + return MapWindowCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook MapWindowCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for MapWindow +// mapWindowRequest writes a MapWindow request to a byte slice. +func mapWindowRequest(c *xgb.Conn, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 8 // request opcode + b += 1 + + b += 1 // padding + + 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 +} + +// NoOperationCookie is a cookie used only for NoOperation requests. +type NoOperationCookie struct { + *xgb.Cookie +} + +// NoOperation sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func NoOperation(c *xgb.Conn) NoOperationCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(noOperationRequest(c), cookie) + return NoOperationCookie{cookie} +} + +// NoOperationChecked sends a checked request. +// If an error occurs, it can be retrieved using NoOperationCookie.Check() +func NoOperationChecked(c *xgb.Conn) NoOperationCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(noOperationRequest(c), cookie) + return NoOperationCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook NoOperationCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for NoOperation +// noOperationRequest writes a NoOperation request to a byte slice. +func noOperationRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 127 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// OpenFontCookie is a cookie used only for OpenFont requests. +type OpenFontCookie struct { + *xgb.Cookie +} + +// OpenFont sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func OpenFont(c *xgb.Conn, Fid Font, NameLen uint16, Name string) OpenFontCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(openFontRequest(c, Fid, NameLen, Name), cookie) + return OpenFontCookie{cookie} +} + +// OpenFontChecked sends a checked request. +// If an error occurs, it can be retrieved using OpenFontCookie.Check() +func OpenFontChecked(c *xgb.Conn, Fid Font, NameLen uint16, Name string) OpenFontCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(openFontRequest(c, Fid, NameLen, Name), cookie) + return OpenFontCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook OpenFontCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for OpenFont +// openFontRequest writes a OpenFont request to a byte slice. +func openFontRequest(c *xgb.Conn, Fid Font, NameLen uint16, Name string) []byte { + size := xgb.Pad((12 + xgb.Pad((int(NameLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 45 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Fid)) + b += 4 + + xgb.Put16(buf[b:], NameLen) + b += 2 + + b += 2 // padding + + copy(buf[b:], Name[:NameLen]) + b += int(NameLen) + + return buf +} + +// PolyArcCookie is a cookie used only for PolyArc requests. +type PolyArcCookie struct { + *xgb.Cookie +} + +// PolyArc sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func PolyArc(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Arcs []Arc) PolyArcCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(polyArcRequest(c, Drawable, Gc, Arcs), cookie) + return PolyArcCookie{cookie} +} + +// PolyArcChecked sends a checked request. +// If an error occurs, it can be retrieved using PolyArcCookie.Check() +func PolyArcChecked(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Arcs []Arc) PolyArcCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(polyArcRequest(c, Drawable, Gc, Arcs), cookie) + return PolyArcCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook PolyArcCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for PolyArc +// polyArcRequest writes a PolyArc request to a byte slice. +func polyArcRequest(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Arcs []Arc) []byte { + size := xgb.Pad((12 + xgb.Pad((len(Arcs) * 12)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 68 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + b += ArcListBytes(buf[b:], Arcs) + + return buf +} + +// PolyFillArcCookie is a cookie used only for PolyFillArc requests. +type PolyFillArcCookie struct { + *xgb.Cookie +} + +// PolyFillArc sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func PolyFillArc(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Arcs []Arc) PolyFillArcCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(polyFillArcRequest(c, Drawable, Gc, Arcs), cookie) + return PolyFillArcCookie{cookie} +} + +// PolyFillArcChecked sends a checked request. +// If an error occurs, it can be retrieved using PolyFillArcCookie.Check() +func PolyFillArcChecked(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Arcs []Arc) PolyFillArcCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(polyFillArcRequest(c, Drawable, Gc, Arcs), cookie) + return PolyFillArcCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook PolyFillArcCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for PolyFillArc +// polyFillArcRequest writes a PolyFillArc request to a byte slice. +func polyFillArcRequest(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Arcs []Arc) []byte { + size := xgb.Pad((12 + xgb.Pad((len(Arcs) * 12)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 71 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + b += ArcListBytes(buf[b:], Arcs) + + return buf +} + +// PolyFillRectangleCookie is a cookie used only for PolyFillRectangle requests. +type PolyFillRectangleCookie struct { + *xgb.Cookie +} + +// PolyFillRectangle sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func PolyFillRectangle(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Rectangles []Rectangle) PolyFillRectangleCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(polyFillRectangleRequest(c, Drawable, Gc, Rectangles), cookie) + return PolyFillRectangleCookie{cookie} +} + +// PolyFillRectangleChecked sends a checked request. +// If an error occurs, it can be retrieved using PolyFillRectangleCookie.Check() +func PolyFillRectangleChecked(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Rectangles []Rectangle) PolyFillRectangleCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(polyFillRectangleRequest(c, Drawable, Gc, Rectangles), cookie) + return PolyFillRectangleCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook PolyFillRectangleCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for PolyFillRectangle +// polyFillRectangleRequest writes a PolyFillRectangle request to a byte slice. +func polyFillRectangleRequest(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Rectangles []Rectangle) []byte { + size := xgb.Pad((12 + xgb.Pad((len(Rectangles) * 8)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 70 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + b += RectangleListBytes(buf[b:], Rectangles) + + return buf +} + +// PolyLineCookie is a cookie used only for PolyLine requests. +type PolyLineCookie struct { + *xgb.Cookie +} + +// PolyLine sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func PolyLine(c *xgb.Conn, CoordinateMode byte, Drawable Drawable, Gc Gcontext, Points []Point) PolyLineCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(polyLineRequest(c, CoordinateMode, Drawable, Gc, Points), cookie) + return PolyLineCookie{cookie} +} + +// PolyLineChecked sends a checked request. +// If an error occurs, it can be retrieved using PolyLineCookie.Check() +func PolyLineChecked(c *xgb.Conn, CoordinateMode byte, Drawable Drawable, Gc Gcontext, Points []Point) PolyLineCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(polyLineRequest(c, CoordinateMode, Drawable, Gc, Points), cookie) + return PolyLineCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook PolyLineCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for PolyLine +// polyLineRequest writes a PolyLine request to a byte slice. +func polyLineRequest(c *xgb.Conn, CoordinateMode byte, Drawable Drawable, Gc Gcontext, Points []Point) []byte { + size := xgb.Pad((12 + xgb.Pad((len(Points) * 4)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 65 // request opcode + b += 1 + + buf[b] = CoordinateMode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + b += PointListBytes(buf[b:], Points) + + return buf +} + +// PolyPointCookie is a cookie used only for PolyPoint requests. +type PolyPointCookie struct { + *xgb.Cookie +} + +// PolyPoint sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func PolyPoint(c *xgb.Conn, CoordinateMode byte, Drawable Drawable, Gc Gcontext, Points []Point) PolyPointCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(polyPointRequest(c, CoordinateMode, Drawable, Gc, Points), cookie) + return PolyPointCookie{cookie} +} + +// PolyPointChecked sends a checked request. +// If an error occurs, it can be retrieved using PolyPointCookie.Check() +func PolyPointChecked(c *xgb.Conn, CoordinateMode byte, Drawable Drawable, Gc Gcontext, Points []Point) PolyPointCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(polyPointRequest(c, CoordinateMode, Drawable, Gc, Points), cookie) + return PolyPointCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook PolyPointCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for PolyPoint +// polyPointRequest writes a PolyPoint request to a byte slice. +func polyPointRequest(c *xgb.Conn, CoordinateMode byte, Drawable Drawable, Gc Gcontext, Points []Point) []byte { + size := xgb.Pad((12 + xgb.Pad((len(Points) * 4)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 64 // request opcode + b += 1 + + buf[b] = CoordinateMode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + b += PointListBytes(buf[b:], Points) + + return buf +} + +// PolyRectangleCookie is a cookie used only for PolyRectangle requests. +type PolyRectangleCookie struct { + *xgb.Cookie +} + +// PolyRectangle sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func PolyRectangle(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Rectangles []Rectangle) PolyRectangleCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(polyRectangleRequest(c, Drawable, Gc, Rectangles), cookie) + return PolyRectangleCookie{cookie} +} + +// PolyRectangleChecked sends a checked request. +// If an error occurs, it can be retrieved using PolyRectangleCookie.Check() +func PolyRectangleChecked(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Rectangles []Rectangle) PolyRectangleCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(polyRectangleRequest(c, Drawable, Gc, Rectangles), cookie) + return PolyRectangleCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook PolyRectangleCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for PolyRectangle +// polyRectangleRequest writes a PolyRectangle request to a byte slice. +func polyRectangleRequest(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Rectangles []Rectangle) []byte { + size := xgb.Pad((12 + xgb.Pad((len(Rectangles) * 8)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 67 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + b += RectangleListBytes(buf[b:], Rectangles) + + return buf +} + +// PolySegmentCookie is a cookie used only for PolySegment requests. +type PolySegmentCookie struct { + *xgb.Cookie +} + +// PolySegment sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func PolySegment(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Segments []Segment) PolySegmentCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(polySegmentRequest(c, Drawable, Gc, Segments), cookie) + return PolySegmentCookie{cookie} +} + +// PolySegmentChecked sends a checked request. +// If an error occurs, it can be retrieved using PolySegmentCookie.Check() +func PolySegmentChecked(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Segments []Segment) PolySegmentCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(polySegmentRequest(c, Drawable, Gc, Segments), cookie) + return PolySegmentCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook PolySegmentCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for PolySegment +// polySegmentRequest writes a PolySegment request to a byte slice. +func polySegmentRequest(c *xgb.Conn, Drawable Drawable, Gc Gcontext, Segments []Segment) []byte { + size := xgb.Pad((12 + xgb.Pad((len(Segments) * 8)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 66 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + b += SegmentListBytes(buf[b:], Segments) + + return buf +} + +// PolyText16Cookie is a cookie used only for PolyText16 requests. +type PolyText16Cookie struct { + *xgb.Cookie +} + +// PolyText16 sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func PolyText16(c *xgb.Conn, Drawable Drawable, Gc Gcontext, X int16, Y int16, Items []byte) PolyText16Cookie { + cookie := c.NewCookie(false, false) + c.NewRequest(polyText16Request(c, Drawable, Gc, X, Y, Items), cookie) + return PolyText16Cookie{cookie} +} + +// PolyText16Checked sends a checked request. +// If an error occurs, it can be retrieved using PolyText16Cookie.Check() +func PolyText16Checked(c *xgb.Conn, Drawable Drawable, Gc Gcontext, X int16, Y int16, Items []byte) PolyText16Cookie { + cookie := c.NewCookie(true, false) + c.NewRequest(polyText16Request(c, Drawable, Gc, X, Y, Items), cookie) + return PolyText16Cookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook PolyText16Cookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for PolyText16 +// polyText16Request writes a PolyText16 request to a byte slice. +func polyText16Request(c *xgb.Conn, Drawable Drawable, Gc Gcontext, X int16, Y int16, Items []byte) []byte { + size := xgb.Pad((16 + xgb.Pad((len(Items) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 75 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + xgb.Put16(buf[b:], uint16(X)) + b += 2 + + xgb.Put16(buf[b:], uint16(Y)) + b += 2 + + copy(buf[b:], Items[:len(Items)]) + b += int(len(Items)) + + return buf +} + +// PolyText8Cookie is a cookie used only for PolyText8 requests. +type PolyText8Cookie struct { + *xgb.Cookie +} + +// PolyText8 sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func PolyText8(c *xgb.Conn, Drawable Drawable, Gc Gcontext, X int16, Y int16, Items []byte) PolyText8Cookie { + cookie := c.NewCookie(false, false) + c.NewRequest(polyText8Request(c, Drawable, Gc, X, Y, Items), cookie) + return PolyText8Cookie{cookie} +} + +// PolyText8Checked sends a checked request. +// If an error occurs, it can be retrieved using PolyText8Cookie.Check() +func PolyText8Checked(c *xgb.Conn, Drawable Drawable, Gc Gcontext, X int16, Y int16, Items []byte) PolyText8Cookie { + cookie := c.NewCookie(true, false) + c.NewRequest(polyText8Request(c, Drawable, Gc, X, Y, Items), cookie) + return PolyText8Cookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook PolyText8Cookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for PolyText8 +// polyText8Request writes a PolyText8 request to a byte slice. +func polyText8Request(c *xgb.Conn, Drawable Drawable, Gc Gcontext, X int16, Y int16, Items []byte) []byte { + size := xgb.Pad((16 + xgb.Pad((len(Items) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 74 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + xgb.Put16(buf[b:], uint16(X)) + b += 2 + + xgb.Put16(buf[b:], uint16(Y)) + b += 2 + + copy(buf[b:], Items[:len(Items)]) + b += int(len(Items)) + + return buf +} + +// PutImageCookie is a cookie used only for PutImage requests. +type PutImageCookie struct { + *xgb.Cookie +} + +// PutImage sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func PutImage(c *xgb.Conn, Format byte, Drawable Drawable, Gc Gcontext, Width uint16, Height uint16, DstX int16, DstY int16, LeftPad byte, Depth byte, Data []byte) PutImageCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(putImageRequest(c, Format, Drawable, Gc, Width, Height, DstX, DstY, LeftPad, Depth, Data), cookie) + return PutImageCookie{cookie} +} + +// PutImageChecked sends a checked request. +// If an error occurs, it can be retrieved using PutImageCookie.Check() +func PutImageChecked(c *xgb.Conn, Format byte, Drawable Drawable, Gc Gcontext, Width uint16, Height uint16, DstX int16, DstY int16, LeftPad byte, Depth byte, Data []byte) PutImageCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(putImageRequest(c, Format, Drawable, Gc, Width, Height, DstX, DstY, LeftPad, Depth, Data), cookie) + return PutImageCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook PutImageCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for PutImage +// putImageRequest writes a PutImage request to a byte slice. +func putImageRequest(c *xgb.Conn, Format byte, Drawable Drawable, Gc Gcontext, Width uint16, Height uint16, DstX int16, DstY int16, LeftPad byte, Depth byte, Data []byte) []byte { + size := xgb.Pad((24 + xgb.Pad((len(Data) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 72 // request opcode + b += 1 + + buf[b] = Format + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + xgb.Put16(buf[b:], Width) + b += 2 + + xgb.Put16(buf[b:], Height) + b += 2 + + xgb.Put16(buf[b:], uint16(DstX)) + b += 2 + + xgb.Put16(buf[b:], uint16(DstY)) + b += 2 + + buf[b] = LeftPad + b += 1 + + buf[b] = Depth + b += 1 + + b += 2 // padding + + copy(buf[b:], Data[:len(Data)]) + b += int(len(Data)) + + return buf +} + +// QueryBestSizeCookie is a cookie used only for QueryBestSize requests. +type QueryBestSizeCookie struct { + *xgb.Cookie +} + +// QueryBestSize sends a checked request. +// If an error occurs, it will be returned with the reply by calling QueryBestSizeCookie.Reply() +func QueryBestSize(c *xgb.Conn, Class byte, Drawable Drawable, Width uint16, Height uint16) QueryBestSizeCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(queryBestSizeRequest(c, Class, Drawable, Width, Height), cookie) + return QueryBestSizeCookie{cookie} +} + +// QueryBestSizeUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func QueryBestSizeUnchecked(c *xgb.Conn, Class byte, Drawable Drawable, Width uint16, Height uint16) QueryBestSizeCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(queryBestSizeRequest(c, Class, Drawable, Width, Height), cookie) + return QueryBestSizeCookie{cookie} +} + +// QueryBestSizeReply represents the data returned from a QueryBestSize request. +type QueryBestSizeReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + Width uint16 + Height uint16 +} + +// Reply blocks and returns the reply data for a QueryBestSize request. +func (cook QueryBestSizeCookie) Reply() (*QueryBestSizeReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return queryBestSizeReply(buf), nil +} + +// queryBestSizeReply reads a byte slice into a QueryBestSizeReply value. +func queryBestSizeReply(buf []byte) *QueryBestSizeReply { + v := new(QueryBestSizeReply) + 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.Get16(buf[b:]) + b += 2 + + v.Height = xgb.Get16(buf[b:]) + b += 2 + + return v +} + +// Write request to wire for QueryBestSize +// queryBestSizeRequest writes a QueryBestSize request to a byte slice. +func queryBestSizeRequest(c *xgb.Conn, Class byte, Drawable Drawable, Width uint16, Height uint16) []byte { + size := 12 + b := 0 + buf := make([]byte, size) + + buf[b] = 97 // request opcode + b += 1 + + buf[b] = Class + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Drawable)) + b += 4 + + xgb.Put16(buf[b:], Width) + b += 2 + + xgb.Put16(buf[b:], Height) + b += 2 + + return buf +} + +// QueryColorsCookie is a cookie used only for QueryColors requests. +type QueryColorsCookie struct { + *xgb.Cookie +} + +// QueryColors sends a checked request. +// If an error occurs, it will be returned with the reply by calling QueryColorsCookie.Reply() +func QueryColors(c *xgb.Conn, Cmap Colormap, Pixels []uint32) QueryColorsCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(queryColorsRequest(c, Cmap, Pixels), cookie) + return QueryColorsCookie{cookie} +} + +// QueryColorsUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func QueryColorsUnchecked(c *xgb.Conn, Cmap Colormap, Pixels []uint32) QueryColorsCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(queryColorsRequest(c, Cmap, Pixels), cookie) + return QueryColorsCookie{cookie} +} + +// QueryColorsReply represents the data returned from a QueryColors request. +type QueryColorsReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + ColorsLen uint16 + // padding: 22 bytes + Colors []Rgb // size: xgb.Pad((int(ColorsLen) * 8)) +} + +// Reply blocks and returns the reply data for a QueryColors request. +func (cook QueryColorsCookie) Reply() (*QueryColorsReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return queryColorsReply(buf), nil +} + +// queryColorsReply reads a byte slice into a QueryColorsReply value. +func queryColorsReply(buf []byte) *QueryColorsReply { + v := new(QueryColorsReply) + 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.ColorsLen = xgb.Get16(buf[b:]) + b += 2 + + b += 22 // padding + + v.Colors = make([]Rgb, v.ColorsLen) + b += RgbReadList(buf[b:], v.Colors) + + return v +} + +// Write request to wire for QueryColors +// queryColorsRequest writes a QueryColors request to a byte slice. +func queryColorsRequest(c *xgb.Conn, Cmap Colormap, Pixels []uint32) []byte { + size := xgb.Pad((8 + xgb.Pad((len(Pixels) * 4)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 91 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + for i := 0; i < int(len(Pixels)); i++ { + xgb.Put32(buf[b:], Pixels[i]) + b += 4 + } + + return buf +} + +// QueryExtensionCookie is a cookie used only for QueryExtension requests. +type QueryExtensionCookie struct { + *xgb.Cookie +} + +// QueryExtension sends a checked request. +// If an error occurs, it will be returned with the reply by calling QueryExtensionCookie.Reply() +func QueryExtension(c *xgb.Conn, NameLen uint16, Name string) QueryExtensionCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(queryExtensionRequest(c, NameLen, Name), cookie) + return QueryExtensionCookie{cookie} +} + +// QueryExtensionUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func QueryExtensionUnchecked(c *xgb.Conn, NameLen uint16, Name string) QueryExtensionCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(queryExtensionRequest(c, NameLen, Name), cookie) + return QueryExtensionCookie{cookie} +} + +// QueryExtensionReply represents the data returned from a QueryExtension request. +type QueryExtensionReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + Present bool + MajorOpcode byte + FirstEvent byte + FirstError byte +} + +// Reply blocks and returns the reply data for a QueryExtension request. +func (cook QueryExtensionCookie) Reply() (*QueryExtensionReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return queryExtensionReply(buf), nil +} + +// queryExtensionReply reads a byte slice into a QueryExtensionReply value. +func queryExtensionReply(buf []byte) *QueryExtensionReply { + v := new(QueryExtensionReply) + 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 + + if buf[b] == 1 { + v.Present = true + } else { + v.Present = false + } + b += 1 + + v.MajorOpcode = buf[b] + b += 1 + + v.FirstEvent = buf[b] + b += 1 + + v.FirstError = buf[b] + b += 1 + + return v +} + +// Write request to wire for QueryExtension +// queryExtensionRequest writes a QueryExtension request to a byte slice. +func queryExtensionRequest(c *xgb.Conn, NameLen uint16, Name string) []byte { + size := xgb.Pad((8 + xgb.Pad((int(NameLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 98 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put16(buf[b:], NameLen) + b += 2 + + b += 2 // padding + + copy(buf[b:], Name[:NameLen]) + b += int(NameLen) + + return buf +} + +// QueryFontCookie is a cookie used only for QueryFont requests. +type QueryFontCookie struct { + *xgb.Cookie +} + +// QueryFont sends a checked request. +// If an error occurs, it will be returned with the reply by calling QueryFontCookie.Reply() +func QueryFont(c *xgb.Conn, Font Fontable) QueryFontCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(queryFontRequest(c, Font), cookie) + return QueryFontCookie{cookie} +} + +// QueryFontUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func QueryFontUnchecked(c *xgb.Conn, Font Fontable) QueryFontCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(queryFontRequest(c, Font), cookie) + return QueryFontCookie{cookie} +} + +// QueryFontReply represents the data returned from a QueryFont request. +type QueryFontReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + MinBounds Charinfo + // padding: 4 bytes + MaxBounds Charinfo + // padding: 4 bytes + MinCharOrByte2 uint16 + MaxCharOrByte2 uint16 + DefaultChar uint16 + PropertiesLen uint16 + DrawDirection byte + MinByte1 byte + MaxByte1 byte + AllCharsExist bool + FontAscent int16 + FontDescent int16 + CharInfosLen uint32 + Properties []Fontprop // size: xgb.Pad((int(PropertiesLen) * 8)) + // alignment gap to multiple of 4 + CharInfos []Charinfo // size: xgb.Pad((int(CharInfosLen) * 12)) +} + +// Reply blocks and returns the reply data for a QueryFont request. +func (cook QueryFontCookie) Reply() (*QueryFontReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return queryFontReply(buf), nil +} + +// queryFontReply reads a byte slice into a QueryFontReply value. +func queryFontReply(buf []byte) *QueryFontReply { + v := new(QueryFontReply) + 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.MinBounds = Charinfo{} + b += CharinfoRead(buf[b:], &v.MinBounds) + + b += 4 // padding + + v.MaxBounds = Charinfo{} + b += CharinfoRead(buf[b:], &v.MaxBounds) + + b += 4 // padding + + v.MinCharOrByte2 = xgb.Get16(buf[b:]) + b += 2 + + v.MaxCharOrByte2 = xgb.Get16(buf[b:]) + b += 2 + + v.DefaultChar = xgb.Get16(buf[b:]) + b += 2 + + v.PropertiesLen = xgb.Get16(buf[b:]) + b += 2 + + v.DrawDirection = buf[b] + b += 1 + + v.MinByte1 = buf[b] + b += 1 + + v.MaxByte1 = buf[b] + b += 1 + + if buf[b] == 1 { + v.AllCharsExist = true + } else { + v.AllCharsExist = false + } + b += 1 + + v.FontAscent = int16(xgb.Get16(buf[b:])) + b += 2 + + v.FontDescent = int16(xgb.Get16(buf[b:])) + b += 2 + + v.CharInfosLen = xgb.Get32(buf[b:]) + b += 4 + + v.Properties = make([]Fontprop, v.PropertiesLen) + b += FontpropReadList(buf[b:], v.Properties) + + b = (b + 3) & ^3 // alignment gap + + v.CharInfos = make([]Charinfo, v.CharInfosLen) + b += CharinfoReadList(buf[b:], v.CharInfos) + + return v +} + +// Write request to wire for QueryFont +// queryFontRequest writes a QueryFont request to a byte slice. +func queryFontRequest(c *xgb.Conn, Font Fontable) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 47 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Font)) + b += 4 + + return buf +} + +// QueryKeymapCookie is a cookie used only for QueryKeymap requests. +type QueryKeymapCookie struct { + *xgb.Cookie +} + +// QueryKeymap sends a checked request. +// If an error occurs, it will be returned with the reply by calling QueryKeymapCookie.Reply() +func QueryKeymap(c *xgb.Conn) QueryKeymapCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(queryKeymapRequest(c), cookie) + return QueryKeymapCookie{cookie} +} + +// QueryKeymapUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func QueryKeymapUnchecked(c *xgb.Conn) QueryKeymapCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(queryKeymapRequest(c), cookie) + return QueryKeymapCookie{cookie} +} + +// QueryKeymapReply represents the data returned from a QueryKeymap request. +type QueryKeymapReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + Keys []byte // size: 32 +} + +// Reply blocks and returns the reply data for a QueryKeymap request. +func (cook QueryKeymapCookie) Reply() (*QueryKeymapReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return queryKeymapReply(buf), nil +} + +// queryKeymapReply reads a byte slice into a QueryKeymapReply value. +func queryKeymapReply(buf []byte) *QueryKeymapReply { + v := new(QueryKeymapReply) + 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.Keys = make([]byte, 32) + copy(v.Keys[:32], buf[b:]) + b += int(32) + + return v +} + +// Write request to wire for QueryKeymap +// queryKeymapRequest writes a QueryKeymap request to a byte slice. +func queryKeymapRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 44 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// QueryPointerCookie is a cookie used only for QueryPointer requests. +type QueryPointerCookie struct { + *xgb.Cookie +} + +// QueryPointer sends a checked request. +// If an error occurs, it will be returned with the reply by calling QueryPointerCookie.Reply() +func QueryPointer(c *xgb.Conn, Window Window) QueryPointerCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(queryPointerRequest(c, Window), cookie) + return QueryPointerCookie{cookie} +} + +// QueryPointerUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func QueryPointerUnchecked(c *xgb.Conn, Window Window) QueryPointerCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(queryPointerRequest(c, Window), cookie) + return QueryPointerCookie{cookie} +} + +// QueryPointerReply represents the data returned from a QueryPointer request. +type QueryPointerReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + SameScreen bool + Root Window + Child Window + RootX int16 + RootY int16 + WinX int16 + WinY int16 + Mask uint16 + // padding: 2 bytes +} + +// Reply blocks and returns the reply data for a QueryPointer request. +func (cook QueryPointerCookie) Reply() (*QueryPointerReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return queryPointerReply(buf), nil +} + +// queryPointerReply reads a byte slice into a QueryPointerReply value. +func queryPointerReply(buf []byte) *QueryPointerReply { + v := new(QueryPointerReply) + b := 1 // skip reply determinant + + if buf[b] == 1 { + v.SameScreen = true + } else { + v.SameScreen = false + } + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.Root = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Child = Window(xgb.Get32(buf[b:])) + b += 4 + + v.RootX = int16(xgb.Get16(buf[b:])) + b += 2 + + v.RootY = int16(xgb.Get16(buf[b:])) + b += 2 + + v.WinX = int16(xgb.Get16(buf[b:])) + b += 2 + + v.WinY = int16(xgb.Get16(buf[b:])) + b += 2 + + v.Mask = xgb.Get16(buf[b:]) + b += 2 + + b += 2 // padding + + return v +} + +// Write request to wire for QueryPointer +// queryPointerRequest writes a QueryPointer request to a byte slice. +func queryPointerRequest(c *xgb.Conn, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 38 // request opcode + b += 1 + + b += 1 // padding + + 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 +} + +// QueryTextExtentsCookie is a cookie used only for QueryTextExtents requests. +type QueryTextExtentsCookie struct { + *xgb.Cookie +} + +// QueryTextExtents sends a checked request. +// If an error occurs, it will be returned with the reply by calling QueryTextExtentsCookie.Reply() +func QueryTextExtents(c *xgb.Conn, Font Fontable, String []Char2b, StringLen uint16) QueryTextExtentsCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(queryTextExtentsRequest(c, Font, String, StringLen), cookie) + return QueryTextExtentsCookie{cookie} +} + +// QueryTextExtentsUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func QueryTextExtentsUnchecked(c *xgb.Conn, Font Fontable, String []Char2b, StringLen uint16) QueryTextExtentsCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(queryTextExtentsRequest(c, Font, String, StringLen), cookie) + return QueryTextExtentsCookie{cookie} +} + +// QueryTextExtentsReply represents the data returned from a QueryTextExtents request. +type QueryTextExtentsReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + DrawDirection byte + FontAscent int16 + FontDescent int16 + OverallAscent int16 + OverallDescent int16 + OverallWidth int32 + OverallLeft int32 + OverallRight int32 +} + +// Reply blocks and returns the reply data for a QueryTextExtents request. +func (cook QueryTextExtentsCookie) Reply() (*QueryTextExtentsReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return queryTextExtentsReply(buf), nil +} + +// queryTextExtentsReply reads a byte slice into a QueryTextExtentsReply value. +func queryTextExtentsReply(buf []byte) *QueryTextExtentsReply { + v := new(QueryTextExtentsReply) + b := 1 // skip reply determinant + + v.DrawDirection = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.FontAscent = int16(xgb.Get16(buf[b:])) + b += 2 + + v.FontDescent = int16(xgb.Get16(buf[b:])) + b += 2 + + v.OverallAscent = int16(xgb.Get16(buf[b:])) + b += 2 + + v.OverallDescent = int16(xgb.Get16(buf[b:])) + b += 2 + + v.OverallWidth = int32(xgb.Get32(buf[b:])) + b += 4 + + v.OverallLeft = int32(xgb.Get32(buf[b:])) + b += 4 + + v.OverallRight = int32(xgb.Get32(buf[b:])) + b += 4 + + return v +} + +// Write request to wire for QueryTextExtents +// queryTextExtentsRequest writes a QueryTextExtents request to a byte slice. +func queryTextExtentsRequest(c *xgb.Conn, Font Fontable, String []Char2b, StringLen uint16) []byte { + size := xgb.Pad((8 + xgb.Pad((len(String) * 2)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 48 // request opcode + b += 1 + + buf[b] = byte((int(StringLen) & 1)) + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Font)) + b += 4 + + b += Char2bListBytes(buf[b:], String) + + // skip writing local field: StringLen (2) :: uint16 + + return buf +} + +// QueryTreeCookie is a cookie used only for QueryTree requests. +type QueryTreeCookie struct { + *xgb.Cookie +} + +// QueryTree sends a checked request. +// If an error occurs, it will be returned with the reply by calling QueryTreeCookie.Reply() +func QueryTree(c *xgb.Conn, Window Window) QueryTreeCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(queryTreeRequest(c, Window), cookie) + return QueryTreeCookie{cookie} +} + +// QueryTreeUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func QueryTreeUnchecked(c *xgb.Conn, Window Window) QueryTreeCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(queryTreeRequest(c, Window), cookie) + return QueryTreeCookie{cookie} +} + +// QueryTreeReply represents the data returned from a QueryTree request. +type QueryTreeReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + // padding: 1 bytes + Root Window + Parent Window + ChildrenLen uint16 + // padding: 14 bytes + Children []Window // size: xgb.Pad((int(ChildrenLen) * 4)) +} + +// Reply blocks and returns the reply data for a QueryTree request. +func (cook QueryTreeCookie) Reply() (*QueryTreeReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return queryTreeReply(buf), nil +} + +// queryTreeReply reads a byte slice into a QueryTreeReply value. +func queryTreeReply(buf []byte) *QueryTreeReply { + v := new(QueryTreeReply) + 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.Root = Window(xgb.Get32(buf[b:])) + b += 4 + + v.Parent = Window(xgb.Get32(buf[b:])) + b += 4 + + v.ChildrenLen = xgb.Get16(buf[b:]) + b += 2 + + b += 14 // padding + + v.Children = make([]Window, v.ChildrenLen) + for i := 0; i < int(v.ChildrenLen); i++ { + v.Children[i] = Window(xgb.Get32(buf[b:])) + b += 4 + } + + return v +} + +// Write request to wire for QueryTree +// queryTreeRequest writes a QueryTree request to a byte slice. +func queryTreeRequest(c *xgb.Conn, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 15 // request opcode + b += 1 + + b += 1 // padding + + 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 +} + +// RecolorCursorCookie is a cookie used only for RecolorCursor requests. +type RecolorCursorCookie struct { + *xgb.Cookie +} + +// RecolorCursor sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func RecolorCursor(c *xgb.Conn, Cursor Cursor, ForeRed uint16, ForeGreen uint16, ForeBlue uint16, BackRed uint16, BackGreen uint16, BackBlue uint16) RecolorCursorCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(recolorCursorRequest(c, Cursor, ForeRed, ForeGreen, ForeBlue, BackRed, BackGreen, BackBlue), cookie) + return RecolorCursorCookie{cookie} +} + +// RecolorCursorChecked sends a checked request. +// If an error occurs, it can be retrieved using RecolorCursorCookie.Check() +func RecolorCursorChecked(c *xgb.Conn, Cursor Cursor, ForeRed uint16, ForeGreen uint16, ForeBlue uint16, BackRed uint16, BackGreen uint16, BackBlue uint16) RecolorCursorCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(recolorCursorRequest(c, Cursor, ForeRed, ForeGreen, ForeBlue, BackRed, BackGreen, BackBlue), cookie) + return RecolorCursorCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook RecolorCursorCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for RecolorCursor +// recolorCursorRequest writes a RecolorCursor request to a byte slice. +func recolorCursorRequest(c *xgb.Conn, Cursor Cursor, ForeRed uint16, ForeGreen uint16, ForeBlue uint16, BackRed uint16, BackGreen uint16, BackBlue uint16) []byte { + size := 20 + b := 0 + buf := make([]byte, size) + + buf[b] = 96 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cursor)) + b += 4 + + xgb.Put16(buf[b:], ForeRed) + b += 2 + + xgb.Put16(buf[b:], ForeGreen) + b += 2 + + xgb.Put16(buf[b:], ForeBlue) + b += 2 + + xgb.Put16(buf[b:], BackRed) + b += 2 + + xgb.Put16(buf[b:], BackGreen) + b += 2 + + xgb.Put16(buf[b:], BackBlue) + b += 2 + + return buf +} + +// ReparentWindowCookie is a cookie used only for ReparentWindow requests. +type ReparentWindowCookie struct { + *xgb.Cookie +} + +// ReparentWindow sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func ReparentWindow(c *xgb.Conn, Window Window, Parent Window, X int16, Y int16) ReparentWindowCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(reparentWindowRequest(c, Window, Parent, X, Y), cookie) + return ReparentWindowCookie{cookie} +} + +// ReparentWindowChecked sends a checked request. +// If an error occurs, it can be retrieved using ReparentWindowCookie.Check() +func ReparentWindowChecked(c *xgb.Conn, Window Window, Parent Window, X int16, Y int16) ReparentWindowCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(reparentWindowRequest(c, Window, Parent, X, Y), cookie) + return ReparentWindowCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook ReparentWindowCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for ReparentWindow +// reparentWindowRequest writes a ReparentWindow request to a byte slice. +func reparentWindowRequest(c *xgb.Conn, Window Window, Parent Window, X int16, Y int16) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 7 // request opcode + b += 1 + + b += 1 // padding + + 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:], uint32(Parent)) + b += 4 + + xgb.Put16(buf[b:], uint16(X)) + b += 2 + + xgb.Put16(buf[b:], uint16(Y)) + b += 2 + + return buf +} + +// RotatePropertiesCookie is a cookie used only for RotateProperties requests. +type RotatePropertiesCookie struct { + *xgb.Cookie +} + +// RotateProperties sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func RotateProperties(c *xgb.Conn, Window Window, AtomsLen uint16, Delta int16, Atoms []Atom) RotatePropertiesCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(rotatePropertiesRequest(c, Window, AtomsLen, Delta, Atoms), cookie) + return RotatePropertiesCookie{cookie} +} + +// RotatePropertiesChecked sends a checked request. +// If an error occurs, it can be retrieved using RotatePropertiesCookie.Check() +func RotatePropertiesChecked(c *xgb.Conn, Window Window, AtomsLen uint16, Delta int16, Atoms []Atom) RotatePropertiesCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(rotatePropertiesRequest(c, Window, AtomsLen, Delta, Atoms), cookie) + return RotatePropertiesCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook RotatePropertiesCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for RotateProperties +// rotatePropertiesRequest writes a RotateProperties request to a byte slice. +func rotatePropertiesRequest(c *xgb.Conn, Window Window, AtomsLen uint16, Delta int16, Atoms []Atom) []byte { + size := xgb.Pad((12 + xgb.Pad((int(AtomsLen) * 4)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 114 // request opcode + b += 1 + + b += 1 // padding + + 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.Put16(buf[b:], AtomsLen) + b += 2 + + xgb.Put16(buf[b:], uint16(Delta)) + b += 2 + + for i := 0; i < int(AtomsLen); i++ { + xgb.Put32(buf[b:], uint32(Atoms[i])) + b += 4 + } + + return buf +} + +// SendEventCookie is a cookie used only for SendEvent requests. +type SendEventCookie struct { + *xgb.Cookie +} + +// SendEvent sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func SendEvent(c *xgb.Conn, Propagate bool, Destination Window, EventMask uint32, Event string) SendEventCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(sendEventRequest(c, Propagate, Destination, EventMask, Event), cookie) + return SendEventCookie{cookie} +} + +// SendEventChecked sends a checked request. +// If an error occurs, it can be retrieved using SendEventCookie.Check() +func SendEventChecked(c *xgb.Conn, Propagate bool, Destination Window, EventMask uint32, Event string) SendEventCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(sendEventRequest(c, Propagate, Destination, EventMask, Event), cookie) + return SendEventCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook SendEventCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for SendEvent +// sendEventRequest writes a SendEvent request to a byte slice. +func sendEventRequest(c *xgb.Conn, Propagate bool, Destination Window, EventMask uint32, Event string) []byte { + size := 44 + b := 0 + buf := make([]byte, size) + + buf[b] = 25 // request opcode + b += 1 + + if Propagate { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Destination)) + b += 4 + + xgb.Put32(buf[b:], EventMask) + b += 4 + + copy(buf[b:], Event[:32]) + b += int(32) + + return buf +} + +// SetAccessControlCookie is a cookie used only for SetAccessControl requests. +type SetAccessControlCookie struct { + *xgb.Cookie +} + +// SetAccessControl sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func SetAccessControl(c *xgb.Conn, Mode byte) SetAccessControlCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(setAccessControlRequest(c, Mode), cookie) + return SetAccessControlCookie{cookie} +} + +// SetAccessControlChecked sends a checked request. +// If an error occurs, it can be retrieved using SetAccessControlCookie.Check() +func SetAccessControlChecked(c *xgb.Conn, Mode byte) SetAccessControlCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(setAccessControlRequest(c, Mode), cookie) + return SetAccessControlCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook SetAccessControlCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for SetAccessControl +// setAccessControlRequest writes a SetAccessControl request to a byte slice. +func setAccessControlRequest(c *xgb.Conn, Mode byte) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 111 // request opcode + b += 1 + + buf[b] = Mode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// SetClipRectanglesCookie is a cookie used only for SetClipRectangles requests. +type SetClipRectanglesCookie struct { + *xgb.Cookie +} + +// SetClipRectangles sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func SetClipRectangles(c *xgb.Conn, Ordering byte, Gc Gcontext, ClipXOrigin int16, ClipYOrigin int16, Rectangles []Rectangle) SetClipRectanglesCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(setClipRectanglesRequest(c, Ordering, Gc, ClipXOrigin, ClipYOrigin, Rectangles), cookie) + return SetClipRectanglesCookie{cookie} +} + +// SetClipRectanglesChecked sends a checked request. +// If an error occurs, it can be retrieved using SetClipRectanglesCookie.Check() +func SetClipRectanglesChecked(c *xgb.Conn, Ordering byte, Gc Gcontext, ClipXOrigin int16, ClipYOrigin int16, Rectangles []Rectangle) SetClipRectanglesCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(setClipRectanglesRequest(c, Ordering, Gc, ClipXOrigin, ClipYOrigin, Rectangles), cookie) + return SetClipRectanglesCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook SetClipRectanglesCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for SetClipRectangles +// setClipRectanglesRequest writes a SetClipRectangles request to a byte slice. +func setClipRectanglesRequest(c *xgb.Conn, Ordering byte, Gc Gcontext, ClipXOrigin int16, ClipYOrigin int16, Rectangles []Rectangle) []byte { + size := xgb.Pad((12 + xgb.Pad((len(Rectangles) * 8)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 59 // request opcode + b += 1 + + buf[b] = Ordering + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + xgb.Put16(buf[b:], uint16(ClipXOrigin)) + b += 2 + + xgb.Put16(buf[b:], uint16(ClipYOrigin)) + b += 2 + + b += RectangleListBytes(buf[b:], Rectangles) + + return buf +} + +// SetCloseDownModeCookie is a cookie used only for SetCloseDownMode requests. +type SetCloseDownModeCookie struct { + *xgb.Cookie +} + +// SetCloseDownMode sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func SetCloseDownMode(c *xgb.Conn, Mode byte) SetCloseDownModeCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(setCloseDownModeRequest(c, Mode), cookie) + return SetCloseDownModeCookie{cookie} +} + +// SetCloseDownModeChecked sends a checked request. +// If an error occurs, it can be retrieved using SetCloseDownModeCookie.Check() +func SetCloseDownModeChecked(c *xgb.Conn, Mode byte) SetCloseDownModeCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(setCloseDownModeRequest(c, Mode), cookie) + return SetCloseDownModeCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook SetCloseDownModeCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for SetCloseDownMode +// setCloseDownModeRequest writes a SetCloseDownMode request to a byte slice. +func setCloseDownModeRequest(c *xgb.Conn, Mode byte) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 112 // request opcode + b += 1 + + buf[b] = Mode + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// SetDashesCookie is a cookie used only for SetDashes requests. +type SetDashesCookie struct { + *xgb.Cookie +} + +// SetDashes sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func SetDashes(c *xgb.Conn, Gc Gcontext, DashOffset uint16, DashesLen uint16, Dashes []byte) SetDashesCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(setDashesRequest(c, Gc, DashOffset, DashesLen, Dashes), cookie) + return SetDashesCookie{cookie} +} + +// SetDashesChecked sends a checked request. +// If an error occurs, it can be retrieved using SetDashesCookie.Check() +func SetDashesChecked(c *xgb.Conn, Gc Gcontext, DashOffset uint16, DashesLen uint16, Dashes []byte) SetDashesCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(setDashesRequest(c, Gc, DashOffset, DashesLen, Dashes), cookie) + return SetDashesCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook SetDashesCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for SetDashes +// setDashesRequest writes a SetDashes request to a byte slice. +func setDashesRequest(c *xgb.Conn, Gc Gcontext, DashOffset uint16, DashesLen uint16, Dashes []byte) []byte { + size := xgb.Pad((12 + xgb.Pad((int(DashesLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 58 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Gc)) + b += 4 + + xgb.Put16(buf[b:], DashOffset) + b += 2 + + xgb.Put16(buf[b:], DashesLen) + b += 2 + + copy(buf[b:], Dashes[:DashesLen]) + b += int(DashesLen) + + return buf +} + +// SetFontPathCookie is a cookie used only for SetFontPath requests. +type SetFontPathCookie struct { + *xgb.Cookie +} + +// SetFontPath sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func SetFontPath(c *xgb.Conn, FontQty uint16, Font []Str) SetFontPathCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(setFontPathRequest(c, FontQty, Font), cookie) + return SetFontPathCookie{cookie} +} + +// SetFontPathChecked sends a checked request. +// If an error occurs, it can be retrieved using SetFontPathCookie.Check() +func SetFontPathChecked(c *xgb.Conn, FontQty uint16, Font []Str) SetFontPathCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(setFontPathRequest(c, FontQty, Font), cookie) + return SetFontPathCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook SetFontPathCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for SetFontPath +// setFontPathRequest writes a SetFontPath request to a byte slice. +func setFontPathRequest(c *xgb.Conn, FontQty uint16, Font []Str) []byte { + size := xgb.Pad((8 + StrListSize(Font))) + b := 0 + buf := make([]byte, size) + + buf[b] = 51 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put16(buf[b:], FontQty) + b += 2 + + b += 2 // padding + + b += StrListBytes(buf[b:], Font) + + return buf +} + +// SetInputFocusCookie is a cookie used only for SetInputFocus requests. +type SetInputFocusCookie struct { + *xgb.Cookie +} + +// SetInputFocus sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func SetInputFocus(c *xgb.Conn, RevertTo byte, Focus Window, Time Timestamp) SetInputFocusCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(setInputFocusRequest(c, RevertTo, Focus, Time), cookie) + return SetInputFocusCookie{cookie} +} + +// SetInputFocusChecked sends a checked request. +// If an error occurs, it can be retrieved using SetInputFocusCookie.Check() +func SetInputFocusChecked(c *xgb.Conn, RevertTo byte, Focus Window, Time Timestamp) SetInputFocusCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(setInputFocusRequest(c, RevertTo, Focus, Time), cookie) + return SetInputFocusCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook SetInputFocusCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for SetInputFocus +// setInputFocusRequest writes a SetInputFocus request to a byte slice. +func setInputFocusRequest(c *xgb.Conn, RevertTo byte, Focus Window, Time Timestamp) []byte { + size := 12 + b := 0 + buf := make([]byte, size) + + buf[b] = 42 // request opcode + b += 1 + + buf[b] = RevertTo + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Focus)) + b += 4 + + xgb.Put32(buf[b:], uint32(Time)) + b += 4 + + return buf +} + +// SetModifierMappingCookie is a cookie used only for SetModifierMapping requests. +type SetModifierMappingCookie struct { + *xgb.Cookie +} + +// SetModifierMapping sends a checked request. +// If an error occurs, it will be returned with the reply by calling SetModifierMappingCookie.Reply() +func SetModifierMapping(c *xgb.Conn, KeycodesPerModifier byte, Keycodes []Keycode) SetModifierMappingCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(setModifierMappingRequest(c, KeycodesPerModifier, Keycodes), cookie) + return SetModifierMappingCookie{cookie} +} + +// SetModifierMappingUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func SetModifierMappingUnchecked(c *xgb.Conn, KeycodesPerModifier byte, Keycodes []Keycode) SetModifierMappingCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(setModifierMappingRequest(c, KeycodesPerModifier, Keycodes), cookie) + return SetModifierMappingCookie{cookie} +} + +// SetModifierMappingReply represents the data returned from a SetModifierMapping request. +type SetModifierMappingReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Status byte +} + +// Reply blocks and returns the reply data for a SetModifierMapping request. +func (cook SetModifierMappingCookie) Reply() (*SetModifierMappingReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return setModifierMappingReply(buf), nil +} + +// setModifierMappingReply reads a byte slice into a SetModifierMappingReply value. +func setModifierMappingReply(buf []byte) *SetModifierMappingReply { + v := new(SetModifierMappingReply) + b := 1 // skip reply determinant + + v.Status = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + return v +} + +// Write request to wire for SetModifierMapping +// setModifierMappingRequest writes a SetModifierMapping request to a byte slice. +func setModifierMappingRequest(c *xgb.Conn, KeycodesPerModifier byte, Keycodes []Keycode) []byte { + size := xgb.Pad((4 + xgb.Pad(((int(KeycodesPerModifier) * 8) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 118 // request opcode + b += 1 + + buf[b] = KeycodesPerModifier + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + for i := 0; i < int((int(KeycodesPerModifier) * 8)); i++ { + buf[b] = byte(Keycodes[i]) + b += 1 + } + + return buf +} + +// SetPointerMappingCookie is a cookie used only for SetPointerMapping requests. +type SetPointerMappingCookie struct { + *xgb.Cookie +} + +// SetPointerMapping sends a checked request. +// If an error occurs, it will be returned with the reply by calling SetPointerMappingCookie.Reply() +func SetPointerMapping(c *xgb.Conn, MapLen byte, Map []byte) SetPointerMappingCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(setPointerMappingRequest(c, MapLen, Map), cookie) + return SetPointerMappingCookie{cookie} +} + +// SetPointerMappingUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func SetPointerMappingUnchecked(c *xgb.Conn, MapLen byte, Map []byte) SetPointerMappingCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(setPointerMappingRequest(c, MapLen, Map), cookie) + return SetPointerMappingCookie{cookie} +} + +// SetPointerMappingReply represents the data returned from a SetPointerMapping request. +type SetPointerMappingReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Status byte +} + +// Reply blocks and returns the reply data for a SetPointerMapping request. +func (cook SetPointerMappingCookie) Reply() (*SetPointerMappingReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return setPointerMappingReply(buf), nil +} + +// setPointerMappingReply reads a byte slice into a SetPointerMappingReply value. +func setPointerMappingReply(buf []byte) *SetPointerMappingReply { + v := new(SetPointerMappingReply) + b := 1 // skip reply determinant + + v.Status = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + return v +} + +// Write request to wire for SetPointerMapping +// setPointerMappingRequest writes a SetPointerMapping request to a byte slice. +func setPointerMappingRequest(c *xgb.Conn, MapLen byte, Map []byte) []byte { + size := xgb.Pad((4 + xgb.Pad((int(MapLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 116 // request opcode + b += 1 + + buf[b] = MapLen + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + copy(buf[b:], Map[:MapLen]) + b += int(MapLen) + + return buf +} + +// SetScreenSaverCookie is a cookie used only for SetScreenSaver requests. +type SetScreenSaverCookie struct { + *xgb.Cookie +} + +// SetScreenSaver sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func SetScreenSaver(c *xgb.Conn, Timeout int16, Interval int16, PreferBlanking byte, AllowExposures byte) SetScreenSaverCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(setScreenSaverRequest(c, Timeout, Interval, PreferBlanking, AllowExposures), cookie) + return SetScreenSaverCookie{cookie} +} + +// SetScreenSaverChecked sends a checked request. +// If an error occurs, it can be retrieved using SetScreenSaverCookie.Check() +func SetScreenSaverChecked(c *xgb.Conn, Timeout int16, Interval int16, PreferBlanking byte, AllowExposures byte) SetScreenSaverCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(setScreenSaverRequest(c, Timeout, Interval, PreferBlanking, AllowExposures), cookie) + return SetScreenSaverCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook SetScreenSaverCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for SetScreenSaver +// setScreenSaverRequest writes a SetScreenSaver request to a byte slice. +func setScreenSaverRequest(c *xgb.Conn, Timeout int16, Interval int16, PreferBlanking byte, AllowExposures byte) []byte { + size := 12 + b := 0 + buf := make([]byte, size) + + buf[b] = 107 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put16(buf[b:], uint16(Timeout)) + b += 2 + + xgb.Put16(buf[b:], uint16(Interval)) + b += 2 + + buf[b] = PreferBlanking + b += 1 + + buf[b] = AllowExposures + b += 1 + + return buf +} + +// SetSelectionOwnerCookie is a cookie used only for SetSelectionOwner requests. +type SetSelectionOwnerCookie struct { + *xgb.Cookie +} + +// SetSelectionOwner sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func SetSelectionOwner(c *xgb.Conn, Owner Window, Selection Atom, Time Timestamp) SetSelectionOwnerCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(setSelectionOwnerRequest(c, Owner, Selection, Time), cookie) + return SetSelectionOwnerCookie{cookie} +} + +// SetSelectionOwnerChecked sends a checked request. +// If an error occurs, it can be retrieved using SetSelectionOwnerCookie.Check() +func SetSelectionOwnerChecked(c *xgb.Conn, Owner Window, Selection Atom, Time Timestamp) SetSelectionOwnerCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(setSelectionOwnerRequest(c, Owner, Selection, Time), cookie) + return SetSelectionOwnerCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook SetSelectionOwnerCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for SetSelectionOwner +// setSelectionOwnerRequest writes a SetSelectionOwner request to a byte slice. +func setSelectionOwnerRequest(c *xgb.Conn, Owner Window, Selection Atom, Time Timestamp) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 22 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Owner)) + b += 4 + + xgb.Put32(buf[b:], uint32(Selection)) + b += 4 + + xgb.Put32(buf[b:], uint32(Time)) + b += 4 + + return buf +} + +// StoreColorsCookie is a cookie used only for StoreColors requests. +type StoreColorsCookie struct { + *xgb.Cookie +} + +// StoreColors sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func StoreColors(c *xgb.Conn, Cmap Colormap, Items []Coloritem) StoreColorsCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(storeColorsRequest(c, Cmap, Items), cookie) + return StoreColorsCookie{cookie} +} + +// StoreColorsChecked sends a checked request. +// If an error occurs, it can be retrieved using StoreColorsCookie.Check() +func StoreColorsChecked(c *xgb.Conn, Cmap Colormap, Items []Coloritem) StoreColorsCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(storeColorsRequest(c, Cmap, Items), cookie) + return StoreColorsCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook StoreColorsCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for StoreColors +// storeColorsRequest writes a StoreColors request to a byte slice. +func storeColorsRequest(c *xgb.Conn, Cmap Colormap, Items []Coloritem) []byte { + size := xgb.Pad((8 + xgb.Pad((len(Items) * 12)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 89 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + b += ColoritemListBytes(buf[b:], Items) + + return buf +} + +// StoreNamedColorCookie is a cookie used only for StoreNamedColor requests. +type StoreNamedColorCookie struct { + *xgb.Cookie +} + +// StoreNamedColor sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func StoreNamedColor(c *xgb.Conn, Flags byte, Cmap Colormap, Pixel uint32, NameLen uint16, Name string) StoreNamedColorCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(storeNamedColorRequest(c, Flags, Cmap, Pixel, NameLen, Name), cookie) + return StoreNamedColorCookie{cookie} +} + +// StoreNamedColorChecked sends a checked request. +// If an error occurs, it can be retrieved using StoreNamedColorCookie.Check() +func StoreNamedColorChecked(c *xgb.Conn, Flags byte, Cmap Colormap, Pixel uint32, NameLen uint16, Name string) StoreNamedColorCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(storeNamedColorRequest(c, Flags, Cmap, Pixel, NameLen, Name), cookie) + return StoreNamedColorCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook StoreNamedColorCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for StoreNamedColor +// storeNamedColorRequest writes a StoreNamedColor request to a byte slice. +func storeNamedColorRequest(c *xgb.Conn, Flags byte, Cmap Colormap, Pixel uint32, NameLen uint16, Name string) []byte { + size := xgb.Pad((16 + xgb.Pad((int(NameLen) * 1)))) + b := 0 + buf := make([]byte, size) + + buf[b] = 90 // request opcode + b += 1 + + buf[b] = Flags + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + xgb.Put32(buf[b:], Pixel) + b += 4 + + xgb.Put16(buf[b:], NameLen) + b += 2 + + b += 2 // padding + + copy(buf[b:], Name[:NameLen]) + b += int(NameLen) + + return buf +} + +// TranslateCoordinatesCookie is a cookie used only for TranslateCoordinates requests. +type TranslateCoordinatesCookie struct { + *xgb.Cookie +} + +// TranslateCoordinates sends a checked request. +// If an error occurs, it will be returned with the reply by calling TranslateCoordinatesCookie.Reply() +func TranslateCoordinates(c *xgb.Conn, SrcWindow Window, DstWindow Window, SrcX int16, SrcY int16) TranslateCoordinatesCookie { + cookie := c.NewCookie(true, true) + c.NewRequest(translateCoordinatesRequest(c, SrcWindow, DstWindow, SrcX, SrcY), cookie) + return TranslateCoordinatesCookie{cookie} +} + +// TranslateCoordinatesUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func TranslateCoordinatesUnchecked(c *xgb.Conn, SrcWindow Window, DstWindow Window, SrcX int16, SrcY int16) TranslateCoordinatesCookie { + cookie := c.NewCookie(false, true) + c.NewRequest(translateCoordinatesRequest(c, SrcWindow, DstWindow, SrcX, SrcY), cookie) + return TranslateCoordinatesCookie{cookie} +} + +// TranslateCoordinatesReply represents the data returned from a TranslateCoordinates request. +type TranslateCoordinatesReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + SameScreen bool + Child Window + DstX int16 + DstY int16 +} + +// Reply blocks and returns the reply data for a TranslateCoordinates request. +func (cook TranslateCoordinatesCookie) Reply() (*TranslateCoordinatesReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return translateCoordinatesReply(buf), nil +} + +// translateCoordinatesReply reads a byte slice into a TranslateCoordinatesReply value. +func translateCoordinatesReply(buf []byte) *TranslateCoordinatesReply { + v := new(TranslateCoordinatesReply) + b := 1 // skip reply determinant + + if buf[b] == 1 { + v.SameScreen = true + } else { + v.SameScreen = false + } + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.Child = Window(xgb.Get32(buf[b:])) + b += 4 + + v.DstX = int16(xgb.Get16(buf[b:])) + b += 2 + + v.DstY = int16(xgb.Get16(buf[b:])) + b += 2 + + return v +} + +// Write request to wire for TranslateCoordinates +// translateCoordinatesRequest writes a TranslateCoordinates request to a byte slice. +func translateCoordinatesRequest(c *xgb.Conn, SrcWindow Window, DstWindow Window, SrcX int16, SrcY int16) []byte { + size := 16 + b := 0 + buf := make([]byte, size) + + buf[b] = 40 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(SrcWindow)) + b += 4 + + xgb.Put32(buf[b:], uint32(DstWindow)) + b += 4 + + xgb.Put16(buf[b:], uint16(SrcX)) + b += 2 + + xgb.Put16(buf[b:], uint16(SrcY)) + b += 2 + + return buf +} + +// UngrabButtonCookie is a cookie used only for UngrabButton requests. +type UngrabButtonCookie struct { + *xgb.Cookie +} + +// UngrabButton sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func UngrabButton(c *xgb.Conn, Button byte, GrabWindow Window, Modifiers uint16) UngrabButtonCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(ungrabButtonRequest(c, Button, GrabWindow, Modifiers), cookie) + return UngrabButtonCookie{cookie} +} + +// UngrabButtonChecked sends a checked request. +// If an error occurs, it can be retrieved using UngrabButtonCookie.Check() +func UngrabButtonChecked(c *xgb.Conn, Button byte, GrabWindow Window, Modifiers uint16) UngrabButtonCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(ungrabButtonRequest(c, Button, GrabWindow, Modifiers), cookie) + return UngrabButtonCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook UngrabButtonCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for UngrabButton +// ungrabButtonRequest writes a UngrabButton request to a byte slice. +func ungrabButtonRequest(c *xgb.Conn, Button byte, GrabWindow Window, Modifiers uint16) []byte { + size := 12 + b := 0 + buf := make([]byte, size) + + buf[b] = 29 // request opcode + b += 1 + + buf[b] = Button + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(GrabWindow)) + b += 4 + + xgb.Put16(buf[b:], Modifiers) + b += 2 + + b += 2 // padding + + return buf +} + +// UngrabKeyCookie is a cookie used only for UngrabKey requests. +type UngrabKeyCookie struct { + *xgb.Cookie +} + +// UngrabKey sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func UngrabKey(c *xgb.Conn, Key Keycode, GrabWindow Window, Modifiers uint16) UngrabKeyCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(ungrabKeyRequest(c, Key, GrabWindow, Modifiers), cookie) + return UngrabKeyCookie{cookie} +} + +// UngrabKeyChecked sends a checked request. +// If an error occurs, it can be retrieved using UngrabKeyCookie.Check() +func UngrabKeyChecked(c *xgb.Conn, Key Keycode, GrabWindow Window, Modifiers uint16) UngrabKeyCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(ungrabKeyRequest(c, Key, GrabWindow, Modifiers), cookie) + return UngrabKeyCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook UngrabKeyCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for UngrabKey +// ungrabKeyRequest writes a UngrabKey request to a byte slice. +func ungrabKeyRequest(c *xgb.Conn, Key Keycode, GrabWindow Window, Modifiers uint16) []byte { + size := 12 + b := 0 + buf := make([]byte, size) + + buf[b] = 34 // request opcode + b += 1 + + buf[b] = byte(Key) + b += 1 + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(GrabWindow)) + b += 4 + + xgb.Put16(buf[b:], Modifiers) + b += 2 + + b += 2 // padding + + return buf +} + +// UngrabKeyboardCookie is a cookie used only for UngrabKeyboard requests. +type UngrabKeyboardCookie struct { + *xgb.Cookie +} + +// UngrabKeyboard sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func UngrabKeyboard(c *xgb.Conn, Time Timestamp) UngrabKeyboardCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(ungrabKeyboardRequest(c, Time), cookie) + return UngrabKeyboardCookie{cookie} +} + +// UngrabKeyboardChecked sends a checked request. +// If an error occurs, it can be retrieved using UngrabKeyboardCookie.Check() +func UngrabKeyboardChecked(c *xgb.Conn, Time Timestamp) UngrabKeyboardCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(ungrabKeyboardRequest(c, Time), cookie) + return UngrabKeyboardCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook UngrabKeyboardCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for UngrabKeyboard +// ungrabKeyboardRequest writes a UngrabKeyboard request to a byte slice. +func ungrabKeyboardRequest(c *xgb.Conn, Time Timestamp) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 32 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Time)) + b += 4 + + return buf +} + +// UngrabPointerCookie is a cookie used only for UngrabPointer requests. +type UngrabPointerCookie struct { + *xgb.Cookie +} + +// UngrabPointer sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func UngrabPointer(c *xgb.Conn, Time Timestamp) UngrabPointerCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(ungrabPointerRequest(c, Time), cookie) + return UngrabPointerCookie{cookie} +} + +// UngrabPointerChecked sends a checked request. +// If an error occurs, it can be retrieved using UngrabPointerCookie.Check() +func UngrabPointerChecked(c *xgb.Conn, Time Timestamp) UngrabPointerCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(ungrabPointerRequest(c, Time), cookie) + return UngrabPointerCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook UngrabPointerCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for UngrabPointer +// ungrabPointerRequest writes a UngrabPointer request to a byte slice. +func ungrabPointerRequest(c *xgb.Conn, Time Timestamp) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 27 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Time)) + b += 4 + + return buf +} + +// UngrabServerCookie is a cookie used only for UngrabServer requests. +type UngrabServerCookie struct { + *xgb.Cookie +} + +// UngrabServer sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func UngrabServer(c *xgb.Conn) UngrabServerCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(ungrabServerRequest(c), cookie) + return UngrabServerCookie{cookie} +} + +// UngrabServerChecked sends a checked request. +// If an error occurs, it can be retrieved using UngrabServerCookie.Check() +func UngrabServerChecked(c *xgb.Conn) UngrabServerCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(ungrabServerRequest(c), cookie) + return UngrabServerCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook UngrabServerCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for UngrabServer +// ungrabServerRequest writes a UngrabServer request to a byte slice. +func ungrabServerRequest(c *xgb.Conn) []byte { + size := 4 + b := 0 + buf := make([]byte, size) + + buf[b] = 37 // request opcode + b += 1 + + b += 1 // padding + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + return buf +} + +// UninstallColormapCookie is a cookie used only for UninstallColormap requests. +type UninstallColormapCookie struct { + *xgb.Cookie +} + +// UninstallColormap sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func UninstallColormap(c *xgb.Conn, Cmap Colormap) UninstallColormapCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(uninstallColormapRequest(c, Cmap), cookie) + return UninstallColormapCookie{cookie} +} + +// UninstallColormapChecked sends a checked request. +// If an error occurs, it can be retrieved using UninstallColormapCookie.Check() +func UninstallColormapChecked(c *xgb.Conn, Cmap Colormap) UninstallColormapCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(uninstallColormapRequest(c, Cmap), cookie) + return UninstallColormapCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook UninstallColormapCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for UninstallColormap +// uninstallColormapRequest writes a UninstallColormap request to a byte slice. +func uninstallColormapRequest(c *xgb.Conn, Cmap Colormap) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 82 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(Cmap)) + b += 4 + + return buf +} + +// UnmapSubwindowsCookie is a cookie used only for UnmapSubwindows requests. +type UnmapSubwindowsCookie struct { + *xgb.Cookie +} + +// UnmapSubwindows sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func UnmapSubwindows(c *xgb.Conn, Window Window) UnmapSubwindowsCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(unmapSubwindowsRequest(c, Window), cookie) + return UnmapSubwindowsCookie{cookie} +} + +// UnmapSubwindowsChecked sends a checked request. +// If an error occurs, it can be retrieved using UnmapSubwindowsCookie.Check() +func UnmapSubwindowsChecked(c *xgb.Conn, Window Window) UnmapSubwindowsCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(unmapSubwindowsRequest(c, Window), cookie) + return UnmapSubwindowsCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook UnmapSubwindowsCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for UnmapSubwindows +// unmapSubwindowsRequest writes a UnmapSubwindows request to a byte slice. +func unmapSubwindowsRequest(c *xgb.Conn, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 11 // request opcode + b += 1 + + b += 1 // padding + + 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 +} + +// UnmapWindowCookie is a cookie used only for UnmapWindow requests. +type UnmapWindowCookie struct { + *xgb.Cookie +} + +// UnmapWindow sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func UnmapWindow(c *xgb.Conn, Window Window) UnmapWindowCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(unmapWindowRequest(c, Window), cookie) + return UnmapWindowCookie{cookie} +} + +// UnmapWindowChecked sends a checked request. +// If an error occurs, it can be retrieved using UnmapWindowCookie.Check() +func UnmapWindowChecked(c *xgb.Conn, Window Window) UnmapWindowCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(unmapWindowRequest(c, Window), cookie) + return UnmapWindowCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook UnmapWindowCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for UnmapWindow +// unmapWindowRequest writes a UnmapWindow request to a byte slice. +func unmapWindowRequest(c *xgb.Conn, Window Window) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + buf[b] = 10 // request opcode + b += 1 + + b += 1 // padding + + 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 +} + +// WarpPointerCookie is a cookie used only for WarpPointer requests. +type WarpPointerCookie struct { + *xgb.Cookie +} + +// WarpPointer sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func WarpPointer(c *xgb.Conn, SrcWindow Window, DstWindow Window, SrcX int16, SrcY int16, SrcWidth uint16, SrcHeight uint16, DstX int16, DstY int16) WarpPointerCookie { + cookie := c.NewCookie(false, false) + c.NewRequest(warpPointerRequest(c, SrcWindow, DstWindow, SrcX, SrcY, SrcWidth, SrcHeight, DstX, DstY), cookie) + return WarpPointerCookie{cookie} +} + +// WarpPointerChecked sends a checked request. +// If an error occurs, it can be retrieved using WarpPointerCookie.Check() +func WarpPointerChecked(c *xgb.Conn, SrcWindow Window, DstWindow Window, SrcX int16, SrcY int16, SrcWidth uint16, SrcHeight uint16, DstX int16, DstY int16) WarpPointerCookie { + cookie := c.NewCookie(true, false) + c.NewRequest(warpPointerRequest(c, SrcWindow, DstWindow, SrcX, SrcY, SrcWidth, SrcHeight, DstX, DstY), cookie) + return WarpPointerCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook WarpPointerCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for WarpPointer +// warpPointerRequest writes a WarpPointer request to a byte slice. +func warpPointerRequest(c *xgb.Conn, SrcWindow Window, DstWindow Window, SrcX int16, SrcY int16, SrcWidth uint16, SrcHeight uint16, DstX int16, DstY int16) []byte { + size := 24 + b := 0 + buf := make([]byte, size) + + buf[b] = 41 // request opcode + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units + b += 2 + + xgb.Put32(buf[b:], uint32(SrcWindow)) + b += 4 + + xgb.Put32(buf[b:], uint32(DstWindow)) + b += 4 + + xgb.Put16(buf[b:], uint16(SrcX)) + b += 2 + + xgb.Put16(buf[b:], uint16(SrcY)) + b += 2 + + xgb.Put16(buf[b:], SrcWidth) + b += 2 + + xgb.Put16(buf[b:], SrcHeight) + b += 2 + + xgb.Put16(buf[b:], uint16(DstX)) + b += 2 + + xgb.Put16(buf[b:], uint16(DstY)) + b += 2 + + return buf +} diff --git a/vendor/github.com/BurntSushi/xgb/xtest/xtest.go b/vendor/github.com/BurntSushi/xgb/xtest/xtest.go new file mode 100644 index 0000000..067dcd2 --- /dev/null +++ b/vendor/github.com/BurntSushi/xgb/xtest/xtest.go @@ -0,0 +1,416 @@ +// Package xtest is the X client API for the XTEST extension. +package xtest + +// This file is automatically generated from xtest.xml. Edit at your peril! + +import ( + "github.com/BurntSushi/xgb" + + "github.com/BurntSushi/xgb/xproto" +) + +// Init must be called before using the XTEST extension. +func Init(c *xgb.Conn) error { + reply, err := xproto.QueryExtension(c, 5, "XTEST").Reply() + switch { + case err != nil: + return err + case !reply.Present: + return xgb.Errorf("No extension named XTEST could be found on on the server.") + } + + c.ExtLock.Lock() + c.Extensions["XTEST"] = reply.MajorOpcode + c.ExtLock.Unlock() + for evNum, fun := range xgb.NewExtEventFuncs["XTEST"] { + xgb.NewEventFuncs[int(reply.FirstEvent)+evNum] = fun + } + for errNum, fun := range xgb.NewExtErrorFuncs["XTEST"] { + xgb.NewErrorFuncs[int(reply.FirstError)+errNum] = fun + } + return nil +} + +func init() { + xgb.NewExtEventFuncs["XTEST"] = make(map[int]xgb.NewEventFun) + xgb.NewExtErrorFuncs["XTEST"] = make(map[int]xgb.NewErrorFun) +} + +const ( + CursorNone = 0 + CursorCurrent = 1 +) + +// 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' + +// CompareCursorCookie is a cookie used only for CompareCursor requests. +type CompareCursorCookie struct { + *xgb.Cookie +} + +// CompareCursor sends a checked request. +// If an error occurs, it will be returned with the reply by calling CompareCursorCookie.Reply() +func CompareCursor(c *xgb.Conn, Window xproto.Window, Cursor xproto.Cursor) CompareCursorCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["XTEST"]; !ok { + panic("Cannot issue request 'CompareCursor' using the uninitialized extension 'XTEST'. xtest.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, true) + c.NewRequest(compareCursorRequest(c, Window, Cursor), cookie) + return CompareCursorCookie{cookie} +} + +// CompareCursorUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func CompareCursorUnchecked(c *xgb.Conn, Window xproto.Window, Cursor xproto.Cursor) CompareCursorCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["XTEST"]; !ok { + panic("Cannot issue request 'CompareCursor' using the uninitialized extension 'XTEST'. xtest.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, true) + c.NewRequest(compareCursorRequest(c, Window, Cursor), cookie) + return CompareCursorCookie{cookie} +} + +// CompareCursorReply represents the data returned from a CompareCursor request. +type CompareCursorReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + Same bool +} + +// Reply blocks and returns the reply data for a CompareCursor request. +func (cook CompareCursorCookie) Reply() (*CompareCursorReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return compareCursorReply(buf), nil +} + +// compareCursorReply reads a byte slice into a CompareCursorReply value. +func compareCursorReply(buf []byte) *CompareCursorReply { + v := new(CompareCursorReply) + b := 1 // skip reply determinant + + if buf[b] == 1 { + v.Same = true + } else { + v.Same = false + } + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + return v +} + +// Write request to wire for CompareCursor +// compareCursorRequest writes a CompareCursor request to a byte slice. +func compareCursorRequest(c *xgb.Conn, Window xproto.Window, Cursor xproto.Cursor) []byte { + size := 12 + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["XTEST"] + 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 + + xgb.Put32(buf[b:], uint32(Cursor)) + b += 4 + + return buf +} + +// FakeInputCookie is a cookie used only for FakeInput requests. +type FakeInputCookie struct { + *xgb.Cookie +} + +// FakeInput sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func FakeInput(c *xgb.Conn, Type byte, Detail uint16, Time uint32, Root xproto.Window, RootX int16, RootY int16, Deviceid byte) FakeInputCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["XTEST"]; !ok { + panic("Cannot issue request 'FakeInput' using the uninitialized extension 'XTEST'. xtest.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, false) + c.NewRequest(fakeInputRequest(c, Type, Detail, Time, Root, RootX, RootY, Deviceid), cookie) + return FakeInputCookie{cookie} +} + +// FakeInputChecked sends a checked request. +// If an error occurs, it can be retrieved using FakeInputCookie.Check() +func FakeInputChecked(c *xgb.Conn, Type byte, Detail uint16, Time uint32, Root xproto.Window, RootX int16, RootY int16, Deviceid byte) FakeInputCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["XTEST"]; !ok { + panic("Cannot issue request 'FakeInput' using the uninitialized extension 'XTEST'. xtest.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, false) + c.NewRequest(fakeInputRequest(c, Type, Detail, Time, Root, RootX, RootY, Deviceid), cookie) + return FakeInputCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook FakeInputCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for FakeInput +// fakeInputRequest writes a FakeInput request to a byte slice. +func fakeInputRequest(c *xgb.Conn, Type byte, Detail uint16, Time uint32, Root xproto.Window, RootX int16, RootY int16, Deviceid byte) []byte { + size := 36 + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["XTEST"] + 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 + + buf[b] = Type + b += 1 + + xgb.Put16(buf[b:], Detail) // write request size in 4-byte units + b += 2 + + b += 1 // padding + + xgb.Put32(buf[b:], Time) + b += 4 + + xgb.Put32(buf[b:], uint32(Root)) + b += 4 + + b += 8 // padding + + xgb.Put16(buf[b:], uint16(RootX)) + b += 2 + + xgb.Put16(buf[b:], uint16(RootY)) + b += 2 + + b += 7 // padding + + buf[b] = Deviceid + b += 1 + + return buf +} + +// GetVersionCookie is a cookie used only for GetVersion requests. +type GetVersionCookie struct { + *xgb.Cookie +} + +// GetVersion sends a checked request. +// If an error occurs, it will be returned with the reply by calling GetVersionCookie.Reply() +func GetVersion(c *xgb.Conn, MajorVersion byte, MinorVersion uint16) GetVersionCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["XTEST"]; !ok { + panic("Cannot issue request 'GetVersion' using the uninitialized extension 'XTEST'. xtest.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, true) + c.NewRequest(getVersionRequest(c, MajorVersion, MinorVersion), cookie) + return GetVersionCookie{cookie} +} + +// GetVersionUnchecked sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GetVersionUnchecked(c *xgb.Conn, MajorVersion byte, MinorVersion uint16) GetVersionCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["XTEST"]; !ok { + panic("Cannot issue request 'GetVersion' using the uninitialized extension 'XTEST'. xtest.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, true) + c.NewRequest(getVersionRequest(c, MajorVersion, MinorVersion), cookie) + return GetVersionCookie{cookie} +} + +// GetVersionReply represents the data returned from a GetVersion request. +type GetVersionReply struct { + Sequence uint16 // sequence number of the request for this reply + Length uint32 // number of bytes in this reply + MajorVersion byte + MinorVersion uint16 +} + +// Reply blocks and returns the reply data for a GetVersion request. +func (cook GetVersionCookie) Reply() (*GetVersionReply, error) { + buf, err := cook.Cookie.Reply() + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return getVersionReply(buf), nil +} + +// getVersionReply reads a byte slice into a GetVersionReply value. +func getVersionReply(buf []byte) *GetVersionReply { + v := new(GetVersionReply) + b := 1 // skip reply determinant + + v.MajorVersion = buf[b] + b += 1 + + v.Sequence = xgb.Get16(buf[b:]) + b += 2 + + v.Length = xgb.Get32(buf[b:]) // 4-byte units + b += 4 + + v.MinorVersion = xgb.Get16(buf[b:]) + b += 2 + + return v +} + +// Write request to wire for GetVersion +// getVersionRequest writes a GetVersion request to a byte slice. +func getVersionRequest(c *xgb.Conn, MajorVersion byte, MinorVersion uint16) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["XTEST"] + 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] = MajorVersion + b += 1 + + b += 1 // padding + + xgb.Put16(buf[b:], MinorVersion) + b += 2 + + return buf +} + +// GrabControlCookie is a cookie used only for GrabControl requests. +type GrabControlCookie struct { + *xgb.Cookie +} + +// GrabControl sends an unchecked request. +// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent. +func GrabControl(c *xgb.Conn, Impervious bool) GrabControlCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["XTEST"]; !ok { + panic("Cannot issue request 'GrabControl' using the uninitialized extension 'XTEST'. xtest.Init(connObj) must be called first.") + } + cookie := c.NewCookie(false, false) + c.NewRequest(grabControlRequest(c, Impervious), cookie) + return GrabControlCookie{cookie} +} + +// GrabControlChecked sends a checked request. +// If an error occurs, it can be retrieved using GrabControlCookie.Check() +func GrabControlChecked(c *xgb.Conn, Impervious bool) GrabControlCookie { + c.ExtLock.RLock() + defer c.ExtLock.RUnlock() + if _, ok := c.Extensions["XTEST"]; !ok { + panic("Cannot issue request 'GrabControl' using the uninitialized extension 'XTEST'. xtest.Init(connObj) must be called first.") + } + cookie := c.NewCookie(true, false) + c.NewRequest(grabControlRequest(c, Impervious), cookie) + return GrabControlCookie{cookie} +} + +// Check returns an error if one occurred for checked requests that are not expecting a reply. +// This cannot be called for requests expecting a reply, nor for unchecked requests. +func (cook GrabControlCookie) Check() error { + return cook.Cookie.Check() +} + +// Write request to wire for GrabControl +// grabControlRequest writes a GrabControl request to a byte slice. +func grabControlRequest(c *xgb.Conn, Impervious bool) []byte { + size := 8 + b := 0 + buf := make([]byte, size) + + c.ExtLock.RLock() + buf[b] = c.Extensions["XTEST"] + 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 + + if Impervious { + buf[b] = 1 + } else { + buf[b] = 0 + } + b += 1 + + b += 3 // padding + + return buf +} diff --git a/vendor/github.com/bendahl/uinput/LICENSE b/vendor/github.com/bendahl/uinput/LICENSE new file mode 100644 index 0000000..d687376 --- /dev/null +++ b/vendor/github.com/bendahl/uinput/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Benjamin Dahlmanns + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/bendahl/uinput/README.md b/vendor/github.com/bendahl/uinput/README.md new file mode 100644 index 0000000..3657dc0 --- /dev/null +++ b/vendor/github.com/bendahl/uinput/README.md @@ -0,0 +1,41 @@ +Uinput [![Build Status](https://travis-ci.org/bendahl/uinput.svg?branch=master)](https://travis-ci.org/bendahl/uinput) [![GoDoc](https://godoc.org/github.com/bendahl/uinput?status.png)](https://godoc.org/github.com/bendahl/uinput) [![Go Report Card](https://goreportcard.com/badge/github.com/bendahl/uinput)](https://goreportcard.com/report/github.com/bendahl/uinput) +==== + +This package provides pure go wrapper functions for the LINUX uinput device, which allows to create virtual input devices +in userspace. At the moment this package offers a virtual keyboard implementation as well as a virtual mouse device and +a touch pad device. +The keyboard can be used to either send single key presses or hold down a specified key and release it later +(useful for building game controllers). The mouse device issues relative positional change events to the x and y axis +of the mouse pointer and may also fire click events (left and right click). More functionality will be added in future +version. +The touch pad, on the other hand can be used to move the mouse cursor to the specified position on the screen and to +issue left and right clicks. Note that you'll need to specify the region size of your screen first though (happens during +device creation). + +Please note that you will need to make sure to have the necessary rights to write to uinput. You can either chmod your +uinput device, or add a rule in /etc/udev/rules.d to allow your user's group or a dedicated group to write to the device. +You may use the following two commands to add the necessary rights for you current user to a file called 99-$USER.rules +(where $USER is your current user's name): +

+echo KERNEL==\"uinput\", GROUP=\"$USER\", MODE:=\"0660\" | sudo tee /etc/udev/rules.d/99-$USER.rules
+sudo udevadm trigger
+
+ +Installation +------------- +Simply check out the repository and use the commands
go build && go install
+The package will then be installed to your local respository, along with the package documentation. +The documentation contains more details on the usage of this package. + +License +-------- +The package falls under the MIT license. Please see the "LICENSE" file for details. + +ToDos +------------------ +All testing has been done on Ubunu 14.04 and 16.04 x86\_64. +Testing for other platforms will need to be done. +To get an idea of the things that are on the current todo list, check out the file "TODO.md". +As always, helpful comments and ideas are always welcome. +Feel free to do some testing on your own if you're up to it. + diff --git a/vendor/github.com/bendahl/uinput/TODO.md b/vendor/github.com/bendahl/uinput/TODO.md new file mode 100644 index 0000000..b0f8544 --- /dev/null +++ b/vendor/github.com/bendahl/uinput/TODO.md @@ -0,0 +1,10 @@ +TODO +==== + +1. ~~Create Tests for the uinput package~~ +2. ~~Migrate code from C to GO~~ +3. ~~Implement relative input~~ +4. ~~Implement absolute input~~ +5. Test on different platforms (besides x86_64) +6. Implement functions to allow mouse button up and down events (for region selects) +7. Extend test cases \ No newline at end of file diff --git a/vendor/github.com/bendahl/uinput/uinput.go b/vendor/github.com/bendahl/uinput/uinput.go new file mode 100644 index 0000000..f9346bf --- /dev/null +++ b/vendor/github.com/bendahl/uinput/uinput.go @@ -0,0 +1,375 @@ +/* +Package uinput is a pure go package that provides access to the userland input device driver uinput on linux systems. +Virtual keyboard devices as well as virtual mouse input devices may be created using this package. +The keycodes and other event definitions, that are available and can be used to trigger input events, +are part of this package ("Key1" for number 1, for example). + +In order to use the virtual keyboard, you will need to follow these three steps: + + 1. Initialize the device + Example: vk, err := CreateKeyboard("/dev/uinput", "Virtual Keyboard") + + 2. Send Button events to the device + Example (print a single D): + err = vk.KeyPress(uinput.KeyD) + + Example (keep moving right by holding down right arrow key): + err = vk.KeyDown(uinput.KeyRight) + + Example (stop moving right by releasing the right arrow key): + err = vk.KeyUp(uinput.KeyRight) + + 3. Close the device + Example: err = vk.Close() + +A virtual mouse input device is just as easy to create and use: + + 1. Initialize the device: + Example: vm, err := CreateMouse("/dev/uinput", "DangerMouse") + + 2. Move the cursor around and issue click events + Example (move mouse right): + err = vm.MoveRight(42) + + Example (move mouse left): + err = vm.MoveLeft(42) + + Example (move mouse up): + err = vm.MoveUp(42) + + Example (move mouse down): + err = vm.MoveDown(42) + + Example (trigger a left click): + err = vm.LeftClick() + + Example (trigger a right click): + err = vm.RightClick() + + 3. Close the device + Example: err = vm.Close() + + +If you'd like to use absolute input events (move the cursor to specific positions on screen), use the touch pad. +Note that you'll need to specify the size of the screen area you want to use when you initialize the +device. Here are a few examples of how to use the virtual touch pad: + + 1. Initialize the device: + Example: vt, err := CreateTouchPad("/dev/uinput", "DontTouchThis", 0, 1024, 0, 768) + + 2. Move the cursor around and issue click events + Example (move cursor to the top left corner of the screen): + err = vt.MoveTo(0, 0) + + Example (move cursor to the position x: 100, y: 250): + err = vt.MoveTo(100, 250) + + Example (trigger a left click): + err = vt.LeftClick() + + Example (trigger a right click): + err = vt.RightClick() + + 3. Close the device + Example: err = vt.Close() + +*/ +package uinput + +import ( + "errors" + "fmt" + "io" + "os" +) + +// A Keyboard is an key event output device. It is used to +// enable a program to simulate HID keyboard input events. +type Keyboard interface { + // KeyPress will cause the key to be pressed and immediately released. + KeyPress(key int) error + + // KeyDown will send a keypress event to an existing keyboard device. + // The key can be any of the predefined keycodes from uinputdefs. + // Note that the key will be "held down" until "KeyUp" is called. + KeyDown(key int) error + + // KeyUp will send a keyrelease event to an existing keyboard device. + // The key can be any of the predefined keycodes from uinputdefs. + KeyUp(key int) error + + io.Closer +} + +type vKeyboard struct { + name []byte + deviceFile *os.File +} + +// A Mouse is a device that will trigger an absolute change event. +// For details see: https://www.kernel.org/doc/Documentation/input/event-codes.txt +type Mouse interface { + // MoveLeft will move the mouse cursor left by the given number of pixel. + MoveLeft(pixel int32) error + + // MoveRight will move the mouse cursor right by the given number of pixel. + MoveRight(pixel int32) error + + // MoveUp will move the mouse cursor up by the given number of pixel. + MoveUp(pixel int32) error + + // MoveDown will move the mouse cursor down by the given number of pixel. + MoveDown(pixel int32) error + + // LeftClick will issue a single left click. + LeftClick() error + + // RightClick will issue a right click. + RightClick() error + + io.Closer +} + +type vMouse struct { + name []byte + deviceFile *os.File +} + +// A TouchPad is an input device that uses absolute axis events, meaning that you can specify +// the exact position the cursor should move to. Therefore, it is necessary to define the size +// of the rectangle in which the cursor may move upon creation of the device. +type TouchPad interface { + // MoveTo will move the cursor to the specified position on the screen + MoveTo(x int32, y int32) error + + // LeftClick will issue a single left click. + LeftClick() error + + // RightClick will issue a right click. + RightClick() error + + io.Closer +} + +type vTouchPad struct { + name []byte + deviceFile *os.File +} + +// CreateTouchPad will create a new touch pad device. note that you will need to define the x and y axis boundaries +// (min and max) within which the cursor maybe moved around. +func CreateTouchPad(path string, name []byte, minX int32, maxX int32, minY int32, maxY int32) (TouchPad, error) { + if path == "" { + return nil, errors.New("device path must not be empty") + } + if len(name) > uinputMaxNameSize { + return nil, fmt.Errorf("device name %s is too long (maximum of %d characters allowed)", name, uinputMaxNameSize) + } + + fd, err := createTouchPad(path, name, minX, maxX, minY, maxY) + if err != nil { + return nil, err + } + + return vTouchPad{name: name, deviceFile: fd}, nil +} + +func (vTouch vTouchPad) MoveTo(x int32, y int32) error { + return sendAbsEvent(vTouch.deviceFile, x, y) +} + +func (vTouch vTouchPad) LeftClick() error { + err := sendBtnEvent(vTouch.deviceFile, evBtnLeft, btnStatePressed) + if err != nil { + return fmt.Errorf("Failed to issue the LeftClick event: %v", err) + } + + err = sendBtnEvent(vTouch.deviceFile, evBtnLeft, btnStateReleased) + if err != nil { + return fmt.Errorf("Failed to issue the KeyUp event: %v", err) + } + + err = syncEvents(vTouch.deviceFile) + if err != nil { + return fmt.Errorf("sync to device file failed: %v", err) + } + return nil +} + +func (vTouch vTouchPad) RightClick() error { + err := sendBtnEvent(vTouch.deviceFile, evBtnRight, btnStatePressed) + if err != nil { + return fmt.Errorf("Failed to issue the RightClick event: %v", err) + } + + err = sendBtnEvent(vTouch.deviceFile, evBtnRight, btnStateReleased) + if err != nil { + return fmt.Errorf("Failed to issue the KeyUp event: %v", err) + } + + err = syncEvents(vTouch.deviceFile) + if err != nil { + return fmt.Errorf("sync to device file failed: %v", err) + } + return nil +} + +func (vTouch vTouchPad) Close() error { + return closeDevice(vTouch.deviceFile) +} + +// CreateMouse will create a new mouse input device. A mouse is a device that allows relative input. +// Relative input means that all changes to the x and y coordinates of the mouse pointer will be +func CreateMouse(path string, name []byte) (Mouse, error) { + if path == "" { + return nil, errors.New("device path must not be empty") + } + if len(name) > uinputMaxNameSize { + return nil, fmt.Errorf("device name %s is too long (maximum of %d characters allowed)", name, uinputMaxNameSize) + } + + fd, err := createMouse(path, name) + if err != nil { + return nil, err + } + + return vMouse{name: name, deviceFile: fd}, nil +} + +// MoveLeft will move the cursor left by the number of pixel specified. +func (vRel vMouse) MoveLeft(pixel int32) error { + return sendRelEvent(vRel.deviceFile, relX, -pixel) +} + +// MoveRight will move the cursor right by the number of pixel specified. +func (vRel vMouse) MoveRight(pixel int32) error { + return sendRelEvent(vRel.deviceFile, relX, pixel) +} + +// MoveUp will move the cursor up by the number of pixel specified. +func (vRel vMouse) MoveUp(pixel int32) error { + return sendRelEvent(vRel.deviceFile, relY, -pixel) +} + +// MoveDown will move the cursor down by the number of pixel specified. +func (vRel vMouse) MoveDown(pixel int32) error { + return sendRelEvent(vRel.deviceFile, relY, pixel) +} + +// LeftClick will issue a LeftClick. +func (vRel vMouse) LeftClick() error { + err := sendBtnEvent(vRel.deviceFile, evBtnLeft, btnStatePressed) + if err != nil { + return fmt.Errorf("Failed to issue the LeftClick event: %v", err) + } + + err = sendBtnEvent(vRel.deviceFile, evBtnLeft, btnStateReleased) + if err != nil { + return fmt.Errorf("Failed to issue the KeyUp event: %v", err) + } + + err = syncEvents(vRel.deviceFile) + if err != nil { + return fmt.Errorf("sync to device file failed: %v", err) + } + return nil +} + +// RightClick will issue a RightClick +func (vRel vMouse) RightClick() error { + err := sendBtnEvent(vRel.deviceFile, evBtnRight, btnStatePressed) + if err != nil { + return fmt.Errorf("Failed to issue the RightClick event: %v", err) + } + + err = sendBtnEvent(vRel.deviceFile, evBtnRight, btnStateReleased) + if err != nil { + return fmt.Errorf("Failed to issue the KeyUp event: %v", err) + } + + err = syncEvents(vRel.deviceFile) + if err != nil { + return fmt.Errorf("sync to device file failed: %v", err) + } + return nil +} + +// Close closes the device and releases the device. +func (vRel vMouse) Close() error { + return closeDevice(vRel.deviceFile) +} + +// CreateKeyboard will create a new keyboard using the given uinput +// device path of the uinput device. +func CreateKeyboard(path string, name []byte) (Keyboard, error) { + if path == "" { + return nil, errors.New("device path must not be empty") + } + if len(name) > uinputMaxNameSize { + return nil, fmt.Errorf("device name %s is too long (maximum of %d characters allowed)", name, uinputMaxNameSize) + } + + fd, err := createVKeyboardDevice(path, name) + if err != nil { + return nil, err + } + + return vKeyboard{name: name, deviceFile: fd}, nil +} + +// KeyPress will issue a single key press (push down a key and then immediately release it). +func (vk vKeyboard) KeyPress(key int) error { + err := sendBtnEvent(vk.deviceFile, key, btnStatePressed) + if err != nil { + return fmt.Errorf("Failed to issue the KeyDown event: %v", err) + } + + err = sendBtnEvent(vk.deviceFile, key, btnStateReleased) + if err != nil { + return fmt.Errorf("Failed to issue the KeyUp event: %v", err) + } + + err = syncEvents(vk.deviceFile) + if err != nil { + return fmt.Errorf("sync to device file failed: %v", err) + } + return nil +} + +// KeyDown will send the key code passed (see uinputdefs.go for available keycodes). Note that unless a key release +// event is sent to the device, the key will remain pressed and therefore input will continuously be generated. Therefore, +// do not forget to call "KeyUp" afterwards. +func (vk vKeyboard) KeyDown(key int) error { + err := sendBtnEvent(vk.deviceFile, key, btnStatePressed) + if err != nil { + return fmt.Errorf("Failed to issue the KeyDown event: %v", err) + } + + err = syncEvents(vk.deviceFile) + if err != nil { + return fmt.Errorf("sync to device file failed: %v", err) + } + return nil +} + +// KeyUp will release the given key passed as a parameter (see uinputdefs.go for available keycodes). In most +// cases it is recommended to call this function immediately after the "KeyDown" function in order to only issue a +// single key press. +func (vk vKeyboard) KeyUp(key int) error { + err := sendBtnEvent(vk.deviceFile, key, btnStatePressed) + if err != nil { + return fmt.Errorf("Failed to issue the KeyUp event: %v", err) + } + + err = syncEvents(vk.deviceFile) + if err != nil { + return fmt.Errorf("sync to device file failed: %v", err) + } + return nil +} + +// Close will close the device and free resources. +// It's usually a good idea to use defer to call this function. +func (vk vKeyboard) Close() error { + return closeDevice(vk.deviceFile) +} diff --git a/vendor/github.com/bendahl/uinput/uinputdefs.go b/vendor/github.com/bendahl/uinput/uinputdefs.go new file mode 100644 index 0000000..a882adc --- /dev/null +++ b/vendor/github.com/bendahl/uinput/uinputdefs.go @@ -0,0 +1,249 @@ +package uinput + +// the constants were copied from input.h for convenience reasons +const ( + keyReserved = 0 + KeyEsc = 1 + Key1 = 2 + Key2 = 3 + Key3 = 4 + Key4 = 5 + Key5 = 6 + Key6 = 7 + Key7 = 8 + Key8 = 9 + Key9 = 10 + Key0 = 11 + KeyMinus = 12 + KeyEqual = 13 + KeyBackspace = 14 + KeyTab = 15 + KeyQ = 16 + KeyW = 17 + KeyE = 18 + KeyR = 19 + KeyT = 20 + KeyY = 21 + KeyU = 22 + KeyI = 23 + KeyO = 24 + KeyP = 25 + KeyLeftbrace = 26 + KeyRightbrace = 27 + KeyEnter = 28 + KeyLeftctrl = 29 + KeyA = 30 + KeyS = 31 + KeyD = 32 + KeyF = 33 + KeyG = 34 + KeyH = 35 + KeyJ = 36 + KeyK = 37 + KeyL = 38 + KeySemicolon = 39 + KeyApostrophe = 40 + KeyGrave = 41 + KeyLeftshift = 42 + KeyBackslash = 43 + KeyZ = 44 + KeyX = 45 + KeyC = 46 + KeyV = 47 + KeyB = 48 + KeyN = 49 + KeyM = 50 + KeyComma = 51 + KeyDot = 52 + KeySlash = 53 + KeyRightshift = 54 + KeyKpasterisk = 55 + KeyLeftalt = 56 + KeySpace = 57 + KeyCapslock = 58 + KeyF1 = 59 + KeyF2 = 60 + KeyF3 = 61 + KeyF4 = 62 + KeyF5 = 63 + KeyF6 = 64 + KeyF7 = 65 + KeyF8 = 66 + KeyF9 = 67 + KeyF10 = 68 + KeyNumlock = 69 + KeyScrolllock = 70 + KeyKp7 = 71 + KeyKp8 = 72 + KeyKp9 = 73 + KeyKpminus = 74 + KeyKp4 = 75 + KeyKp5 = 76 + KeyKp6 = 77 + KeyKpplus = 78 + KeyKp1 = 79 + KeyKp2 = 80 + KeyKp3 = 81 + KeyKp0 = 82 + KeyKpdot = 83 + KeyZenkakuhankaku = 85 + Key102Nd = 86 + KeyF11 = 87 + KeyF12 = 88 + KeyRo = 89 + KeyKatakana = 90 + KeyHiragana = 91 + KeyHenkan = 92 + KeyKatakanahiragana = 93 + KeyMuhenkan = 94 + KeyKpjpcomma = 95 + KeyKpenter = 96 + KeyRightctrl = 97 + KeyKpslash = 98 + KeySysrq = 99 + KeyRightalt = 100 + KeyLinefeed = 101 + KeyHome = 102 + KeyUp = 103 + KeyPageup = 104 + KeyLeft = 105 + KeyRight = 106 + KeyEnd = 107 + KeyDown = 108 + KeyPagedown = 109 + KeyInsert = 110 + KeyDelete = 111 + KeyMacro = 112 + KeyMute = 113 + KeyVolumedown = 114 + KeyVolumeup = 115 + KeyPower = 116 /*ScSystemPowerDown*/ + KeyKpequal = 117 + KeyKpplusminus = 118 + KeyPause = 119 + KeyScale = 120 /*AlCompizScale(Expose)*/ + KeyKpcomma = 121 + KeyHangeul = 122 + KeyHanja = 123 + KeyYen = 124 + KeyLeftmeta = 125 + KeyRightmeta = 126 + KeyCompose = 127 + KeyStop = 128 /*AcStop*/ + KeyAgain = 129 + KeyProps = 130 /*AcProperties*/ + KeyUndo = 131 /*AcUndo*/ + KeyFront = 132 + KeyCopy = 133 /*AcCopy*/ + KeyOpen = 134 /*AcOpen*/ + KeyPaste = 135 /*AcPaste*/ + KeyFind = 136 /*AcSearch*/ + KeyCut = 137 /*AcCut*/ + KeyHelp = 138 /*AlIntegratedHelpCenter*/ + KeyMenu = 139 /*Menu(ShowMenu)*/ + KeyCalc = 140 /*AlCalculator*/ + KeySetup = 141 + KeySleep = 142 /*ScSystemSleep*/ + KeyWakeup = 143 /*SystemWakeUp*/ + KeyFile = 144 /*AlLocalMachineBrowser*/ + KeySendfile = 145 + KeyDeletefile = 146 + KeyXfer = 147 + KeyProg1 = 148 + KeyProg2 = 149 + KeyWww = 150 /*AlInternetBrowser*/ + KeyMsdos = 151 + KeyCoffee = 152 /*AlTerminalLock/Screensaver*/ + KeyDirection = 153 + KeyCyclewindows = 154 + KeyMail = 155 + KeyBookmarks = 156 /*AcBookmarks*/ + KeyComputer = 157 + KeyBack = 158 /*AcBack*/ + KeyForward = 159 /*AcForward*/ + KeyClosecd = 160 + KeyEjectcd = 161 + KeyEjectclosecd = 162 + KeyNextsong = 163 + KeyPlaypause = 164 + KeyPrevioussong = 165 + KeyStopcd = 166 + KeyRecord = 167 + KeyRewind = 168 + KeyPhone = 169 /*MediaSelectTelephone*/ + KeyIso = 170 + KeyConfig = 171 /*AlConsumerControlConfiguration*/ + KeyHomepage = 172 /*AcHome*/ + KeyRefresh = 173 /*AcRefresh*/ + KeyExit = 174 /*AcExit*/ + KeyMove = 175 + KeyEdit = 176 + KeyScrollup = 177 + KeyScrolldown = 178 + KeyKpleftparen = 179 + KeyKprightparen = 180 + KeyNew = 181 /*AcNew*/ + KeyRedo = 182 /*AcRedo/Repeat*/ + KeyF13 = 183 + KeyF14 = 184 + KeyF15 = 185 + KeyF16 = 186 + KeyF17 = 187 + KeyF18 = 188 + KeyF19 = 189 + KeyF20 = 190 + KeyF21 = 191 + KeyF22 = 192 + KeyF23 = 193 + KeyF24 = 194 + KeyPlaycd = 200 + KeyPausecd = 201 + KeyProg3 = 202 + KeyProg4 = 203 + KeyDashboard = 204 /*AlDashboard*/ + KeySuspend = 205 + KeyClose = 206 /*AcClose*/ + KeyPlay = 207 + KeyFastforward = 208 + KeyBassboost = 209 + KeyPrint = 210 /*AcPrint*/ + KeyHp = 211 + KeyCamera = 212 + KeySound = 213 + KeyQuestion = 214 + KeyEmail = 215 + KeyChat = 216 + KeySearch = 217 + KeyConnect = 218 + KeyFinance = 219 /*AlCheckbook/Finance*/ + KeySport = 220 + KeyShop = 221 + KeyAlterase = 222 + KeyCancel = 223 /*AcCancel*/ + KeyBrightnessdown = 224 + KeyBrightnessup = 225 + KeyMedia = 226 + KeySwitchvideomode = 227 /*CycleBetweenAvailableVideo */ + KeyKbdillumtoggle = 228 + KeyKbdillumdown = 229 + KeyKbdillumup = 230 + KeySend = 231 /*AcSend*/ + KeyReply = 232 /*AcReply*/ + KeyForwardmail = 233 /*AcForwardMsg*/ + KeySave = 234 /*AcSave*/ + KeyDocuments = 235 + KeyBattery = 236 + KeyBluetooth = 237 + KeyWlan = 238 + KeyUwb = 239 + KeyUnknown = 240 + KeyVideoNext = 241 /*DriveNextVideoSource*/ + KeyVideoPrev = 242 /*DrivePreviousVideoSource*/ + KeyBrightnessCycle = 243 /*BrightnessUp,AfterMaxIsMin*/ + KeyBrightnessZero = 244 /*BrightnessOff,UseAmbient*/ + KeyDisplayOff = 245 /*DisplayDeviceToOffState*/ + KeyWimax = 246 + KeyRfkill = 247 /*KeyThatControlsAllRadios*/ + KeyMicmute = 248 /*Mute/UnmuteTheMicrophone*/ + keyMax = 248 // highest key currently defined +) diff --git a/vendor/github.com/bendahl/uinput/uinputwrapper.go b/vendor/github.com/bendahl/uinput/uinputwrapper.go new file mode 100644 index 0000000..3f16897 --- /dev/null +++ b/vendor/github.com/bendahl/uinput/uinputwrapper.go @@ -0,0 +1,369 @@ +package uinput + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "os" + "syscall" + "time" +) + +// types needed from uinput.h +const ( + uinputMaxNameSize = 80 + uiDevCreate = 0x5501 + uiDevDestroy = 0x5502 + uiSetEvBit = 0x40045564 + uiSetKeyBit = 0x40045565 + uiSetRelBit = 0x40045566 + uiSetAbsBit = 0x40045567 + busUsb = 0x03 +) + +// input event codes as specified in input-event-codes.h +const ( + evSyn = 0x00 + evKey = 0x01 + evRel = 0x02 + evAbs = 0x03 + relX = 0x0 + relY = 0x1 + absX = 0x0 + absY = 0x1 + synReport = 0 + evBtnLeft = 0x110 + evBtnRight = 0x111 +) + +const ( + btnStateReleased = 0 + btnStatePressed = 1 + absSize = 64 +) + +type inputID struct { + Bustype uint16 + Vendor uint16 + Product uint16 + Version uint16 +} + +// translated to go from uinput.h +type uinputUserDev struct { + Name [uinputMaxNameSize]byte + ID inputID + EffectsMax uint32 + Absmax [absSize]int32 + Absmin [absSize]int32 + Absfuzz [absSize]int32 + Absflat [absSize]int32 +} + +// translated to go from input.h +type inputEvent struct { + Time syscall.Timeval + Type uint16 + Code uint16 + Value int32 +} + +func closeDevice(deviceFile *os.File) (err error) { + err = releaseDevice(deviceFile) + if err != nil { + return fmt.Errorf("failed to close device: %v", err) + } + return deviceFile.Close() +} + +func releaseDevice(deviceFile *os.File) (err error) { + return ioctl(deviceFile, uiDevDestroy, uintptr(0)) +} + +func createDeviceFile(path string) (fd *os.File, err error) { + deviceFile, err := os.OpenFile(path, syscall.O_WRONLY|syscall.O_NONBLOCK, 0660) + if err != nil { + return nil, errors.New("could not open device file") + } + return deviceFile, err +} + +func registerDevice(deviceFile *os.File, evType uintptr) error { + err := ioctl(deviceFile, uiSetEvBit, evType) + if err != nil { + err = releaseDevice(deviceFile) + if err != nil { + deviceFile.Close() + return fmt.Errorf("failed to close device: %v", err) + } + deviceFile.Close() + return fmt.Errorf("invalid file handle returned from ioctl: %v", err) + } + return nil +} + +func createVKeyboardDevice(path string, name []byte) (fd *os.File, err error) { + deviceFile, err := createDeviceFile(path) + if err != nil { + return nil, fmt.Errorf("failed to create virtual keyboard device: %v", err) + } + + err = registerDevice(deviceFile, uintptr(evKey)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register virtual keyboard device: %v", err) + } + + // register key events + for i := 0; i < keyMax; i++ { + err = ioctl(deviceFile, uiSetKeyBit, uintptr(i)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register key number %d: %v", i, err) + } + } + + return createUsbDevice(deviceFile, + uinputUserDev{ + Name: toUinputName(name), + ID: inputID{ + Bustype: busUsb, + Vendor: 0x4711, + Product: 0x0815, + Version: 1}}) +} + +func toUinputName(name []byte) (uinputName [uinputMaxNameSize]byte) { + var fixedSizeName [uinputMaxNameSize]byte + copy(fixedSizeName[:], name) + return fixedSizeName +} + +func createTouchPad(path string, name []byte, minX int32, maxX int32, minY int32, maxY int32) (fd *os.File, err error) { + deviceFile, err := createDeviceFile(path) + if err != nil { + return nil, fmt.Errorf("could not create absolute axis input device: %v", err) + } + + err = registerDevice(deviceFile, uintptr(evKey)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register key device: %v", err) + } + // register button events (in order to enable left and right click) + err = ioctl(deviceFile, uiSetKeyBit, uintptr(evBtnLeft)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register left click event: %v", err) + } + err = ioctl(deviceFile, uiSetKeyBit, uintptr(evBtnRight)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register right click event: %v", err) + } + + err = registerDevice(deviceFile, uintptr(evAbs)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register absolute axis input device: %v", err) + } + + // register x and y axis events + err = ioctl(deviceFile, uiSetAbsBit, uintptr(absX)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register absolute x axis events: %v", err) + } + err = ioctl(deviceFile, uiSetAbsBit, uintptr(absY)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register absolute y axis events: %v", err) + } + + var absMin [absSize]int32 + absMin[absX] = minX + absMin[absY] = minY + + var absMax [absSize]int32 + absMax[absX] = maxX + absMax[absY] = maxY + + return createUsbDevice(deviceFile, + uinputUserDev{ + Name: toUinputName(name), + ID: inputID{ + Bustype: busUsb, + Vendor: 0x4711, + Product: 0x0817, + Version: 1}, + Absmin: absMin, + Absmax: absMax}) +} + +func createMouse(path string, name []byte) (fd *os.File, err error) { + deviceFile, err := createDeviceFile(path) + if err != nil { + return nil, fmt.Errorf("could not create relative axis input device: %v", err) + } + + err = registerDevice(deviceFile, uintptr(evKey)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register key device: %v", err) + } + // register button events (in order to enable left and right click) + err = ioctl(deviceFile, uiSetKeyBit, uintptr(evBtnLeft)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register left click event: %v", err) + } + err = ioctl(deviceFile, uiSetKeyBit, uintptr(evBtnRight)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register right click event: %v", err) + } + + err = registerDevice(deviceFile, uintptr(evRel)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register relative axis input device: %v", err) + } + + // register x and y axis events + err = ioctl(deviceFile, uiSetRelBit, uintptr(relX)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register relative x axis events: %v", err) + } + err = ioctl(deviceFile, uiSetRelBit, uintptr(relY)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to register relative y axis events: %v", err) + } + + return createUsbDevice(deviceFile, + uinputUserDev{ + Name: toUinputName(name), + ID: inputID{ + Bustype: busUsb, + Vendor: 0x4711, + Product: 0x0816, + Version: 1}}) +} + +func createUsbDevice(deviceFile *os.File, dev uinputUserDev) (fd *os.File, err error) { + buf := new(bytes.Buffer) + err = binary.Write(buf, binary.LittleEndian, dev) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to write user device buffer: %v", err) + } + _, err = deviceFile.Write(buf.Bytes()) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to write uidev struct to device file: %v", err) + } + + err = ioctl(deviceFile, uiDevCreate, uintptr(0)) + if err != nil { + deviceFile.Close() + return nil, fmt.Errorf("failed to create device: %v", err) + } + + time.Sleep(time.Millisecond * 200) + + return deviceFile, err +} + +func sendBtnEvent(deviceFile *os.File, key int, btnState int) (err error) { + buf, err := inputEventToBuffer(inputEvent{ + Time: syscall.Timeval{Sec: 0, Usec: 0}, + Type: evKey, + Code: uint16(key), + Value: int32(btnState)}) + if err != nil { + return fmt.Errorf("key event could not be set: %v", err) + } + _, err = deviceFile.Write(buf) + if err != nil { + return fmt.Errorf("writing btnEvent structure to the device file failed: %v", err) + } + return err +} + +func sendAbsEvent(deviceFile *os.File, xPos int32, yPos int32) error { + var ev [2]inputEvent + ev[0].Type = evAbs + ev[0].Code = absX + ev[0].Value = xPos + + ev[1].Type = evAbs + ev[1].Code = absY + ev[1].Value = yPos + + for _, iev := range ev { + buf, err := inputEventToBuffer(iev) + if err != nil { + return fmt.Errorf("writing abs event failed: %v", err) + } + + _, err = deviceFile.Write(buf) + if err != nil { + return fmt.Errorf("failed to write abs event to device file: %v", err) + } + } + + return syncEvents(deviceFile) +} + +func sendRelEvent(deviceFile *os.File, eventCode uint16, pixel int32) error { + iev := inputEvent{ + Time: syscall.Timeval{Sec: 0, Usec: 0}, + Type: evRel, + Code: eventCode, + Value: pixel} + + buf, err := inputEventToBuffer(iev) + if err != nil { + return fmt.Errorf("writing abs event failed: %v", err) + } + + _, err = deviceFile.Write(buf) + if err != nil { + return fmt.Errorf("failed to write rel event to device file: %v", err) + } + + return syncEvents(deviceFile) +} + +func syncEvents(deviceFile *os.File) (err error) { + buf, err := inputEventToBuffer(inputEvent{ + Time: syscall.Timeval{Sec: 0, Usec: 0}, + Type: evSyn, + Code: 0, + Value: int32(synReport)}) + if err != nil { + return fmt.Errorf("writing sync event failed: %v", err) + } + _, err = deviceFile.Write(buf) + return err +} + +func inputEventToBuffer(iev inputEvent) (buffer []byte, err error) { + buf := new(bytes.Buffer) + err = binary.Write(buf, binary.LittleEndian, iev) + if err != nil { + return nil, fmt.Errorf("failed to write input event to buffer: %v", err) + } + return buf.Bytes(), nil +} + +// original function taken from: https://github.com/tianon/debian-golang-pty/blob/master/ioctl.go +func ioctl(deviceFile *os.File, cmd, ptr uintptr) error { + _, _, errorCode := syscall.Syscall(syscall.SYS_IOCTL, deviceFile.Fd(), cmd, ptr) + if errorCode != 0 { + return errorCode + } + return nil +} diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/davecgh/go-spew/LICENSE new file mode 100644 index 0000000..bb67332 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2012-2013 Dave Collins + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go new file mode 100644 index 0000000..d42a0bc --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go @@ -0,0 +1,152 @@ +// Copyright (c) 2015 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is not running on Google App Engine, compiled by GopherJS, and +// "-tags safe" is not added to the go build command line. The "disableunsafe" +// tag is deprecated and thus should not be used. +// +build !js,!appengine,!safe,!disableunsafe + +package spew + +import ( + "reflect" + "unsafe" +) + +const ( + // UnsafeDisabled is a build-time constant which specifies whether or + // not access to the unsafe package is available. + UnsafeDisabled = false + + // ptrSize is the size of a pointer on the current arch. + ptrSize = unsafe.Sizeof((*byte)(nil)) +) + +var ( + // offsetPtr, offsetScalar, and offsetFlag are the offsets for the + // internal reflect.Value fields. These values are valid before golang + // commit ecccf07e7f9d which changed the format. The are also valid + // after commit 82f48826c6c7 which changed the format again to mirror + // the original format. Code in the init function updates these offsets + // as necessary. + offsetPtr = uintptr(ptrSize) + offsetScalar = uintptr(0) + offsetFlag = uintptr(ptrSize * 2) + + // flagKindWidth and flagKindShift indicate various bits that the + // reflect package uses internally to track kind information. + // + // flagRO indicates whether or not the value field of a reflect.Value is + // read-only. + // + // flagIndir indicates whether the value field of a reflect.Value is + // the actual data or a pointer to the data. + // + // These values are valid before golang commit 90a7c3c86944 which + // changed their positions. Code in the init function updates these + // flags as necessary. + flagKindWidth = uintptr(5) + flagKindShift = uintptr(flagKindWidth - 1) + flagRO = uintptr(1 << 0) + flagIndir = uintptr(1 << 1) +) + +func init() { + // Older versions of reflect.Value stored small integers directly in the + // ptr field (which is named val in the older versions). Versions + // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named + // scalar for this purpose which unfortunately came before the flag + // field, so the offset of the flag field is different for those + // versions. + // + // This code constructs a new reflect.Value from a known small integer + // and checks if the size of the reflect.Value struct indicates it has + // the scalar field. When it does, the offsets are updated accordingly. + vv := reflect.ValueOf(0xf00) + if unsafe.Sizeof(vv) == (ptrSize * 4) { + offsetScalar = ptrSize * 2 + offsetFlag = ptrSize * 3 + } + + // Commit 90a7c3c86944 changed the flag positions such that the low + // order bits are the kind. This code extracts the kind from the flags + // field and ensures it's the correct type. When it's not, the flag + // order has been changed to the newer format, so the flags are updated + // accordingly. + upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) + upfv := *(*uintptr)(upf) + flagKindMask := uintptr((1<>flagKindShift != uintptr(reflect.Int) { + flagKindShift = 0 + flagRO = 1 << 5 + flagIndir = 1 << 6 + + // Commit adf9b30e5594 modified the flags to separate the + // flagRO flag into two bits which specifies whether or not the + // field is embedded. This causes flagIndir to move over a bit + // and means that flagRO is the combination of either of the + // original flagRO bit and the new bit. + // + // This code detects the change by extracting what used to be + // the indirect bit to ensure it's set. When it's not, the flag + // order has been changed to the newer format, so the flags are + // updated accordingly. + if upfv&flagIndir == 0 { + flagRO = 3 << 5 + flagIndir = 1 << 7 + } + } +} + +// unsafeReflectValue converts the passed reflect.Value into a one that bypasses +// the typical safety restrictions preventing access to unaddressable and +// unexported data. It works by digging the raw pointer to the underlying +// value out of the protected value and generating a new unprotected (unsafe) +// reflect.Value to it. +// +// This allows us to check for implementations of the Stringer and error +// interfaces to be used for pretty printing ordinarily unaddressable and +// inaccessible values such as unexported struct fields. +func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { + indirects := 1 + vt := v.Type() + upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) + rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) + if rvf&flagIndir != 0 { + vt = reflect.PtrTo(v.Type()) + indirects++ + } else if offsetScalar != 0 { + // The value is in the scalar field when it's not one of the + // reference types. + switch vt.Kind() { + case reflect.Uintptr: + case reflect.Chan: + case reflect.Func: + case reflect.Map: + case reflect.Ptr: + case reflect.UnsafePointer: + default: + upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + + offsetScalar) + } + } + + pv := reflect.NewAt(vt, upv) + rv = pv + for i := 0; i < indirects; i++ { + rv = rv.Elem() + } + return rv +} diff --git a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go new file mode 100644 index 0000000..e47a4e7 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go @@ -0,0 +1,38 @@ +// Copyright (c) 2015 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is running on Google App Engine, compiled by GopherJS, or +// "-tags safe" is added to the go build command line. The "disableunsafe" +// tag is deprecated and thus should not be used. +// +build js appengine safe disableunsafe + +package spew + +import "reflect" + +const ( + // UnsafeDisabled is a build-time constant which specifies whether or + // not access to the unsafe package is available. + UnsafeDisabled = true +) + +// unsafeReflectValue typically converts the passed reflect.Value into a one +// that bypasses the typical safety restrictions preventing access to +// unaddressable and unexported data. However, doing this relies on access to +// the unsafe package. This is a stub version which simply returns the passed +// reflect.Value when the unsafe package is not available. +func unsafeReflectValue(v reflect.Value) reflect.Value { + return v +} diff --git a/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/davecgh/go-spew/spew/common.go new file mode 100644 index 0000000..14f02dc --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/common.go @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2013 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "io" + "reflect" + "sort" + "strconv" +) + +// Some constants in the form of bytes to avoid string overhead. This mirrors +// the technique used in the fmt package. +var ( + panicBytes = []byte("(PANIC=") + plusBytes = []byte("+") + iBytes = []byte("i") + trueBytes = []byte("true") + falseBytes = []byte("false") + interfaceBytes = []byte("(interface {})") + commaNewlineBytes = []byte(",\n") + newlineBytes = []byte("\n") + openBraceBytes = []byte("{") + openBraceNewlineBytes = []byte("{\n") + closeBraceBytes = []byte("}") + asteriskBytes = []byte("*") + colonBytes = []byte(":") + colonSpaceBytes = []byte(": ") + openParenBytes = []byte("(") + closeParenBytes = []byte(")") + spaceBytes = []byte(" ") + pointerChainBytes = []byte("->") + nilAngleBytes = []byte("") + maxNewlineBytes = []byte("\n") + maxShortBytes = []byte("") + circularBytes = []byte("") + circularShortBytes = []byte("") + invalidAngleBytes = []byte("") + openBracketBytes = []byte("[") + closeBracketBytes = []byte("]") + percentBytes = []byte("%") + precisionBytes = []byte(".") + openAngleBytes = []byte("<") + closeAngleBytes = []byte(">") + openMapBytes = []byte("map[") + closeMapBytes = []byte("]") + lenEqualsBytes = []byte("len=") + capEqualsBytes = []byte("cap=") +) + +// hexDigits is used to map a decimal value to a hex digit. +var hexDigits = "0123456789abcdef" + +// catchPanic handles any panics that might occur during the handleMethods +// calls. +func catchPanic(w io.Writer, v reflect.Value) { + if err := recover(); err != nil { + w.Write(panicBytes) + fmt.Fprintf(w, "%v", err) + w.Write(closeParenBytes) + } +} + +// handleMethods attempts to call the Error and String methods on the underlying +// type the passed reflect.Value represents and outputes the result to Writer w. +// +// It handles panics in any called methods by catching and displaying the error +// as the formatted value. +func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { + // We need an interface to check if the type implements the error or + // Stringer interface. However, the reflect package won't give us an + // interface on certain things like unexported struct fields in order + // to enforce visibility rules. We use unsafe, when it's available, + // to bypass these restrictions since this package does not mutate the + // values. + if !v.CanInterface() { + if UnsafeDisabled { + return false + } + + v = unsafeReflectValue(v) + } + + // Choose whether or not to do error and Stringer interface lookups against + // the base type or a pointer to the base type depending on settings. + // Technically calling one of these methods with a pointer receiver can + // mutate the value, however, types which choose to satisify an error or + // Stringer interface with a pointer receiver should not be mutating their + // state inside these interface methods. + if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { + v = unsafeReflectValue(v) + } + if v.CanAddr() { + v = v.Addr() + } + + // Is it an error or Stringer? + switch iface := v.Interface().(type) { + case error: + defer catchPanic(w, v) + if cs.ContinueOnMethod { + w.Write(openParenBytes) + w.Write([]byte(iface.Error())) + w.Write(closeParenBytes) + w.Write(spaceBytes) + return false + } + + w.Write([]byte(iface.Error())) + return true + + case fmt.Stringer: + defer catchPanic(w, v) + if cs.ContinueOnMethod { + w.Write(openParenBytes) + w.Write([]byte(iface.String())) + w.Write(closeParenBytes) + w.Write(spaceBytes) + return false + } + w.Write([]byte(iface.String())) + return true + } + return false +} + +// printBool outputs a boolean value as true or false to Writer w. +func printBool(w io.Writer, val bool) { + if val { + w.Write(trueBytes) + } else { + w.Write(falseBytes) + } +} + +// printInt outputs a signed integer value to Writer w. +func printInt(w io.Writer, val int64, base int) { + w.Write([]byte(strconv.FormatInt(val, base))) +} + +// printUint outputs an unsigned integer value to Writer w. +func printUint(w io.Writer, val uint64, base int) { + w.Write([]byte(strconv.FormatUint(val, base))) +} + +// printFloat outputs a floating point value using the specified precision, +// which is expected to be 32 or 64bit, to Writer w. +func printFloat(w io.Writer, val float64, precision int) { + w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) +} + +// printComplex outputs a complex value using the specified float precision +// for the real and imaginary parts to Writer w. +func printComplex(w io.Writer, c complex128, floatPrecision int) { + r := real(c) + w.Write(openParenBytes) + w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) + i := imag(c) + if i >= 0 { + w.Write(plusBytes) + } + w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) + w.Write(iBytes) + w.Write(closeParenBytes) +} + +// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x' +// prefix to Writer w. +func printHexPtr(w io.Writer, p uintptr) { + // Null pointer. + num := uint64(p) + if num == 0 { + w.Write(nilAngleBytes) + return + } + + // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix + buf := make([]byte, 18) + + // It's simpler to construct the hex string right to left. + base := uint64(16) + i := len(buf) - 1 + for num >= base { + buf[i] = hexDigits[num%base] + num /= base + i-- + } + buf[i] = hexDigits[num] + + // Add '0x' prefix. + i-- + buf[i] = 'x' + i-- + buf[i] = '0' + + // Strip unused leading bytes. + buf = buf[i:] + w.Write(buf) +} + +// valuesSorter implements sort.Interface to allow a slice of reflect.Value +// elements to be sorted. +type valuesSorter struct { + values []reflect.Value + strings []string // either nil or same len and values + cs *ConfigState +} + +// newValuesSorter initializes a valuesSorter instance, which holds a set of +// surrogate keys on which the data should be sorted. It uses flags in +// ConfigState to decide if and how to populate those surrogate keys. +func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { + vs := &valuesSorter{values: values, cs: cs} + if canSortSimply(vs.values[0].Kind()) { + return vs + } + if !cs.DisableMethods { + vs.strings = make([]string, len(values)) + for i := range vs.values { + b := bytes.Buffer{} + if !handleMethods(cs, &b, vs.values[i]) { + vs.strings = nil + break + } + vs.strings[i] = b.String() + } + } + if vs.strings == nil && cs.SpewKeys { + vs.strings = make([]string, len(values)) + for i := range vs.values { + vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) + } + } + return vs +} + +// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted +// directly, or whether it should be considered for sorting by surrogate keys +// (if the ConfigState allows it). +func canSortSimply(kind reflect.Kind) bool { + // This switch parallels valueSortLess, except for the default case. + switch kind { + case reflect.Bool: + return true + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return true + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.String: + return true + case reflect.Uintptr: + return true + case reflect.Array: + return true + } + return false +} + +// Len returns the number of values in the slice. It is part of the +// sort.Interface implementation. +func (s *valuesSorter) Len() int { + return len(s.values) +} + +// Swap swaps the values at the passed indices. It is part of the +// sort.Interface implementation. +func (s *valuesSorter) Swap(i, j int) { + s.values[i], s.values[j] = s.values[j], s.values[i] + if s.strings != nil { + s.strings[i], s.strings[j] = s.strings[j], s.strings[i] + } +} + +// valueSortLess returns whether the first value should sort before the second +// value. It is used by valueSorter.Less as part of the sort.Interface +// implementation. +func valueSortLess(a, b reflect.Value) bool { + switch a.Kind() { + case reflect.Bool: + return !a.Bool() && b.Bool() + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return a.Int() < b.Int() + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return a.Uint() < b.Uint() + case reflect.Float32, reflect.Float64: + return a.Float() < b.Float() + case reflect.String: + return a.String() < b.String() + case reflect.Uintptr: + return a.Uint() < b.Uint() + case reflect.Array: + // Compare the contents of both arrays. + l := a.Len() + for i := 0; i < l; i++ { + av := a.Index(i) + bv := b.Index(i) + if av.Interface() == bv.Interface() { + continue + } + return valueSortLess(av, bv) + } + } + return a.String() < b.String() +} + +// Less returns whether the value at index i should sort before the +// value at index j. It is part of the sort.Interface implementation. +func (s *valuesSorter) Less(i, j int) bool { + if s.strings == nil { + return valueSortLess(s.values[i], s.values[j]) + } + return s.strings[i] < s.strings[j] +} + +// sortValues is a sort function that handles both native types and any type that +// can be converted to error or Stringer. Other inputs are sorted according to +// their Value.String() value to ensure display stability. +func sortValues(values []reflect.Value, cs *ConfigState) { + if len(values) == 0 { + return + } + sort.Sort(newValuesSorter(values, cs)) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/config.go b/vendor/github.com/davecgh/go-spew/spew/config.go new file mode 100644 index 0000000..9db83c6 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/config.go @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2013 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "io" + "os" +) + +// ConfigState houses the configuration options used by spew to format and +// display values. There is a global instance, Config, that is used to control +// all top-level Formatter and Dump functionality. Each ConfigState instance +// provides methods equivalent to the top-level functions. +// +// The zero value for ConfigState provides no indentation. You would typically +// want to set it to a space or a tab. +// +// Alternatively, you can use NewDefaultConfig to get a ConfigState instance +// with default settings. See the documentation of NewDefaultConfig for default +// values. +type ConfigState struct { + // Indent specifies the string to use for each indentation level. The + // global config instance that all top-level functions use set this to a + // single space by default. If you would like more indentation, you might + // set this to a tab with "\t" or perhaps two spaces with " ". + Indent string + + // MaxDepth controls the maximum number of levels to descend into nested + // data structures. The default, 0, means there is no limit. + // + // NOTE: Circular data structures are properly detected, so it is not + // necessary to set this value unless you specifically want to limit deeply + // nested data structures. + MaxDepth int + + // DisableMethods specifies whether or not error and Stringer interfaces are + // invoked for types that implement them. + DisableMethods bool + + // DisablePointerMethods specifies whether or not to check for and invoke + // error and Stringer interfaces on types which only accept a pointer + // receiver when the current type is not a pointer. + // + // NOTE: This might be an unsafe action since calling one of these methods + // with a pointer receiver could technically mutate the value, however, + // in practice, types which choose to satisify an error or Stringer + // interface with a pointer receiver should not be mutating their state + // inside these interface methods. As a result, this option relies on + // access to the unsafe package, so it will not have any effect when + // running in environments without access to the unsafe package such as + // Google App Engine or with the "safe" build tag specified. + DisablePointerMethods bool + + // DisablePointerAddresses specifies whether to disable the printing of + // pointer addresses. This is useful when diffing data structures in tests. + DisablePointerAddresses bool + + // DisableCapacities specifies whether to disable the printing of capacities + // for arrays, slices, maps and channels. This is useful when diffing + // data structures in tests. + DisableCapacities bool + + // ContinueOnMethod specifies whether or not recursion should continue once + // a custom error or Stringer interface is invoked. The default, false, + // means it will print the results of invoking the custom error or Stringer + // interface and return immediately instead of continuing to recurse into + // the internals of the data type. + // + // NOTE: This flag does not have any effect if method invocation is disabled + // via the DisableMethods or DisablePointerMethods options. + ContinueOnMethod bool + + // SortKeys specifies map keys should be sorted before being printed. Use + // this to have a more deterministic, diffable output. Note that only + // native types (bool, int, uint, floats, uintptr and string) and types + // that support the error or Stringer interfaces (if methods are + // enabled) are supported, with other types sorted according to the + // reflect.Value.String() output which guarantees display stability. + SortKeys bool + + // SpewKeys specifies that, as a last resort attempt, map keys should + // be spewed to strings and sorted by those strings. This is only + // considered if SortKeys is true. + SpewKeys bool +} + +// Config is the active configuration of the top-level functions. +// The configuration can be changed by modifying the contents of spew.Config. +var Config = ConfigState{Indent: " "} + +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the formatted string as a value that satisfies error. See NewFormatter +// for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, c.convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, c.convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, c.convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a Formatter interface returned by c.NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, c.convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Print(a ...interface{}) (n int, err error) { + return fmt.Print(c.convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, c.convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Println(a ...interface{}) (n int, err error) { + return fmt.Println(c.convertArgs(a)...) +} + +// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprint(a ...interface{}) string { + return fmt.Sprint(c.convertArgs(a)...) +} + +// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, c.convertArgs(a)...) +} + +// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it +// were passed with a Formatter interface returned by c.NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintln(a ...interface{}) string { + return fmt.Sprintln(c.convertArgs(a)...) +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +c.Printf, c.Println, or c.Printf. +*/ +func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(c, v) +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { + fdump(c, w, a...) +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output + +The configuration options are controlled by modifying the public members +of c. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to +get the formatted result as a string. +*/ +func (c *ConfigState) Dump(a ...interface{}) { + fdump(c, os.Stdout, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as Dump. +func (c *ConfigState) Sdump(a ...interface{}) string { + var buf bytes.Buffer + fdump(c, &buf, a...) + return buf.String() +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a spew Formatter interface using +// the ConfigState associated with s. +func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = newFormatter(c, arg) + } + return formatters +} + +// NewDefaultConfig returns a ConfigState with the following default settings. +// +// Indent: " " +// MaxDepth: 0 +// DisableMethods: false +// DisablePointerMethods: false +// ContinueOnMethod: false +// SortKeys: false +func NewDefaultConfig() *ConfigState { + return &ConfigState{Indent: " "} +} diff --git a/vendor/github.com/davecgh/go-spew/spew/doc.go b/vendor/github.com/davecgh/go-spew/spew/doc.go new file mode 100644 index 0000000..5be0c40 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/doc.go @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2013 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* +Package spew implements a deep pretty printer for Go data structures to aid in +debugging. + +A quick overview of the additional features spew provides over the built-in +printing facilities for Go data types are as follows: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output (only when using + Dump style) + +There are two different approaches spew allows for dumping Go data structures: + + * Dump style which prints with newlines, customizable indentation, + and additional debug information such as types and all pointer addresses + used to indirect to the final value + * A custom Formatter interface that integrates cleanly with the standard fmt + package and replaces %v, %+v, %#v, and %#+v to provide inline printing + similar to the default %v while providing the additional functionality + outlined above and passing unsupported format verbs such as %x and %q + along to fmt + +Quick Start + +This section demonstrates how to quickly get started with spew. See the +sections below for further details on formatting and configuration options. + +To dump a variable with full newlines, indentation, type, and pointer +information use Dump, Fdump, or Sdump: + spew.Dump(myVar1, myVar2, ...) + spew.Fdump(someWriter, myVar1, myVar2, ...) + str := spew.Sdump(myVar1, myVar2, ...) + +Alternatively, if you would prefer to use format strings with a compacted inline +printing style, use the convenience wrappers Printf, Fprintf, etc with +%v (most compact), %+v (adds pointer addresses), %#v (adds types), or +%#+v (adds types and pointer addresses): + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +Configuration Options + +Configuration of spew is handled by fields in the ConfigState type. For +convenience, all of the top-level functions use a global state available +via the spew.Config global. + +It is also possible to create a ConfigState instance that provides methods +equivalent to the top-level functions. This allows concurrent configuration +options. See the ConfigState documentation for more details. + +The following configuration options are available: + * Indent + String to use for each indentation level for Dump functions. + It is a single space by default. A popular alternative is "\t". + + * MaxDepth + Maximum number of levels to descend into nested data structures. + There is no limit by default. + + * DisableMethods + Disables invocation of error and Stringer interface methods. + Method invocation is enabled by default. + + * DisablePointerMethods + Disables invocation of error and Stringer interface methods on types + which only accept pointer receivers from non-pointer variables. + Pointer method invocation is enabled by default. + + * ContinueOnMethod + Enables recursion into types after invoking error and Stringer interface + methods. Recursion after method invocation is disabled by default. + + * SortKeys + Specifies map keys should be sorted before being printed. Use + this to have a more deterministic, diffable output. Note that + only native types (bool, int, uint, floats, uintptr and string) + and types which implement error or Stringer interfaces are + supported with other types sorted according to the + reflect.Value.String() output which guarantees display + stability. Natural map order is used by default. + + * SpewKeys + Specifies that, as a last resort attempt, map keys should be + spewed to strings and sorted by those strings. This is only + considered if SortKeys is true. + +Dump Usage + +Simply call spew.Dump with a list of variables you want to dump: + + spew.Dump(myVar1, myVar2, ...) + +You may also call spew.Fdump if you would prefer to output to an arbitrary +io.Writer. For example, to dump to standard error: + + spew.Fdump(os.Stderr, myVar1, myVar2, ...) + +A third option is to call spew.Sdump to get the formatted output as a string: + + str := spew.Sdump(myVar1, myVar2, ...) + +Sample Dump Output + +See the Dump example for details on the setup of the types and variables being +shown here. + + (main.Foo) { + unexportedField: (*main.Bar)(0xf84002e210)({ + flag: (main.Flag) flagTwo, + data: (uintptr) + }), + ExportedField: (map[interface {}]interface {}) (len=1) { + (string) (len=3) "one": (bool) true + } + } + +Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C +command as shown. + ([]uint8) (len=32 cap=32) { + 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | + 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| + 00000020 31 32 |12| + } + +Custom Formatter + +Spew provides a custom formatter that implements the fmt.Formatter interface +so that it integrates cleanly with standard fmt package printing functions. The +formatter is useful for inline printing of smaller data types similar to the +standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Custom Formatter Usage + +The simplest way to make use of the spew custom formatter is to call one of the +convenience functions such as spew.Printf, spew.Println, or spew.Printf. The +functions have syntax you are most likely already familiar with: + + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Println(myVar, myVar2) + spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +See the Index for the full list convenience functions. + +Sample Formatter Output + +Double pointer to a uint8: + %v: <**>5 + %+v: <**>(0xf8400420d0->0xf8400420c8)5 + %#v: (**uint8)5 + %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 + +Pointer to circular struct with a uint8 field and a pointer to itself: + %v: <*>{1 <*>} + %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} + %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} + %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} + +See the Printf example for details on the setup of variables being shown +here. + +Errors + +Since it is possible for custom Stringer/error interfaces to panic, spew +detects them and handles them internally by printing the panic information +inline with the output. Since spew is intended to provide deep pretty printing +capabilities on structures, it intentionally does not return any errors. +*/ +package spew diff --git a/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/davecgh/go-spew/spew/dump.go new file mode 100644 index 0000000..95f9dbf --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/dump.go @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2013 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "encoding/hex" + "fmt" + "io" + "os" + "reflect" + "regexp" + "strconv" + "strings" +) + +var ( + // uint8Type is a reflect.Type representing a uint8. It is used to + // convert cgo types to uint8 slices for hexdumping. + uint8Type = reflect.TypeOf(uint8(0)) + + // cCharRE is a regular expression that matches a cgo char. + // It is used to detect character arrays to hexdump them. + cCharRE = regexp.MustCompile("^.*\\._Ctype_char$") + + // cUnsignedCharRE is a regular expression that matches a cgo unsigned + // char. It is used to detect unsigned character arrays to hexdump + // them. + cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$") + + // cUint8tCharRE is a regular expression that matches a cgo uint8_t. + // It is used to detect uint8_t arrays to hexdump them. + cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$") +) + +// dumpState contains information about the state of a dump operation. +type dumpState struct { + w io.Writer + depth int + pointers map[uintptr]int + ignoreNextType bool + ignoreNextIndent bool + cs *ConfigState +} + +// indent performs indentation according to the depth level and cs.Indent +// option. +func (d *dumpState) indent() { + if d.ignoreNextIndent { + d.ignoreNextIndent = false + return + } + d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) +} + +// unpackValue returns values inside of non-nil interfaces when possible. +// This is useful for data types like structs, arrays, slices, and maps which +// can contain varying types packed inside an interface. +func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { + if v.Kind() == reflect.Interface && !v.IsNil() { + v = v.Elem() + } + return v +} + +// dumpPtr handles formatting of pointers by indirecting them as necessary. +func (d *dumpState) dumpPtr(v reflect.Value) { + // Remove pointers at or below the current depth from map used to detect + // circular refs. + for k, depth := range d.pointers { + if depth >= d.depth { + delete(d.pointers, k) + } + } + + // Keep list of all dereferenced pointers to show later. + pointerChain := make([]uintptr, 0) + + // Figure out how many levels of indirection there are by dereferencing + // pointers and unpacking interfaces down the chain while detecting circular + // references. + nilFound := false + cycleFound := false + indirects := 0 + ve := v + for ve.Kind() == reflect.Ptr { + if ve.IsNil() { + nilFound = true + break + } + indirects++ + addr := ve.Pointer() + pointerChain = append(pointerChain, addr) + if pd, ok := d.pointers[addr]; ok && pd < d.depth { + cycleFound = true + indirects-- + break + } + d.pointers[addr] = d.depth + + ve = ve.Elem() + if ve.Kind() == reflect.Interface { + if ve.IsNil() { + nilFound = true + break + } + ve = ve.Elem() + } + } + + // Display type information. + d.w.Write(openParenBytes) + d.w.Write(bytes.Repeat(asteriskBytes, indirects)) + d.w.Write([]byte(ve.Type().String())) + d.w.Write(closeParenBytes) + + // Display pointer information. + if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { + d.w.Write(openParenBytes) + for i, addr := range pointerChain { + if i > 0 { + d.w.Write(pointerChainBytes) + } + printHexPtr(d.w, addr) + } + d.w.Write(closeParenBytes) + } + + // Display dereferenced value. + d.w.Write(openParenBytes) + switch { + case nilFound == true: + d.w.Write(nilAngleBytes) + + case cycleFound == true: + d.w.Write(circularBytes) + + default: + d.ignoreNextType = true + d.dump(ve) + } + d.w.Write(closeParenBytes) +} + +// dumpSlice handles formatting of arrays and slices. Byte (uint8 under +// reflection) arrays and slices are dumped in hexdump -C fashion. +func (d *dumpState) dumpSlice(v reflect.Value) { + // Determine whether this type should be hex dumped or not. Also, + // for types which should be hexdumped, try to use the underlying data + // first, then fall back to trying to convert them to a uint8 slice. + var buf []uint8 + doConvert := false + doHexDump := false + numEntries := v.Len() + if numEntries > 0 { + vt := v.Index(0).Type() + vts := vt.String() + switch { + // C types that need to be converted. + case cCharRE.MatchString(vts): + fallthrough + case cUnsignedCharRE.MatchString(vts): + fallthrough + case cUint8tCharRE.MatchString(vts): + doConvert = true + + // Try to use existing uint8 slices and fall back to converting + // and copying if that fails. + case vt.Kind() == reflect.Uint8: + // We need an addressable interface to convert the type + // to a byte slice. However, the reflect package won't + // give us an interface on certain things like + // unexported struct fields in order to enforce + // visibility rules. We use unsafe, when available, to + // bypass these restrictions since this package does not + // mutate the values. + vs := v + if !vs.CanInterface() || !vs.CanAddr() { + vs = unsafeReflectValue(vs) + } + if !UnsafeDisabled { + vs = vs.Slice(0, numEntries) + + // Use the existing uint8 slice if it can be + // type asserted. + iface := vs.Interface() + if slice, ok := iface.([]uint8); ok { + buf = slice + doHexDump = true + break + } + } + + // The underlying data needs to be converted if it can't + // be type asserted to a uint8 slice. + doConvert = true + } + + // Copy and convert the underlying type if needed. + if doConvert && vt.ConvertibleTo(uint8Type) { + // Convert and copy each element into a uint8 byte + // slice. + buf = make([]uint8, numEntries) + for i := 0; i < numEntries; i++ { + vv := v.Index(i) + buf[i] = uint8(vv.Convert(uint8Type).Uint()) + } + doHexDump = true + } + } + + // Hexdump the entire slice as needed. + if doHexDump { + indent := strings.Repeat(d.cs.Indent, d.depth) + str := indent + hex.Dump(buf) + str = strings.Replace(str, "\n", "\n"+indent, -1) + str = strings.TrimRight(str, d.cs.Indent) + d.w.Write([]byte(str)) + return + } + + // Recursively call dump for each item. + for i := 0; i < numEntries; i++ { + d.dump(d.unpackValue(v.Index(i))) + if i < (numEntries - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } +} + +// dump is the main workhorse for dumping a value. It uses the passed reflect +// value to figure out what kind of object we are dealing with and formats it +// appropriately. It is a recursive function, however circular data structures +// are detected and handled properly. +func (d *dumpState) dump(v reflect.Value) { + // Handle invalid reflect values immediately. + kind := v.Kind() + if kind == reflect.Invalid { + d.w.Write(invalidAngleBytes) + return + } + + // Handle pointers specially. + if kind == reflect.Ptr { + d.indent() + d.dumpPtr(v) + return + } + + // Print type information unless already handled elsewhere. + if !d.ignoreNextType { + d.indent() + d.w.Write(openParenBytes) + d.w.Write([]byte(v.Type().String())) + d.w.Write(closeParenBytes) + d.w.Write(spaceBytes) + } + d.ignoreNextType = false + + // Display length and capacity if the built-in len and cap functions + // work with the value's kind and the len/cap itself is non-zero. + valueLen, valueCap := 0, 0 + switch v.Kind() { + case reflect.Array, reflect.Slice, reflect.Chan: + valueLen, valueCap = v.Len(), v.Cap() + case reflect.Map, reflect.String: + valueLen = v.Len() + } + if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 { + d.w.Write(openParenBytes) + if valueLen != 0 { + d.w.Write(lenEqualsBytes) + printInt(d.w, int64(valueLen), 10) + } + if !d.cs.DisableCapacities && valueCap != 0 { + if valueLen != 0 { + d.w.Write(spaceBytes) + } + d.w.Write(capEqualsBytes) + printInt(d.w, int64(valueCap), 10) + } + d.w.Write(closeParenBytes) + d.w.Write(spaceBytes) + } + + // Call Stringer/error interfaces if they exist and the handle methods flag + // is enabled + if !d.cs.DisableMethods { + if (kind != reflect.Invalid) && (kind != reflect.Interface) { + if handled := handleMethods(d.cs, d.w, v); handled { + return + } + } + } + + switch kind { + case reflect.Invalid: + // Do nothing. We should never get here since invalid has already + // been handled above. + + case reflect.Bool: + printBool(d.w, v.Bool()) + + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + printInt(d.w, v.Int(), 10) + + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + printUint(d.w, v.Uint(), 10) + + case reflect.Float32: + printFloat(d.w, v.Float(), 32) + + case reflect.Float64: + printFloat(d.w, v.Float(), 64) + + case reflect.Complex64: + printComplex(d.w, v.Complex(), 32) + + case reflect.Complex128: + printComplex(d.w, v.Complex(), 64) + + case reflect.Slice: + if v.IsNil() { + d.w.Write(nilAngleBytes) + break + } + fallthrough + + case reflect.Array: + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + d.dumpSlice(v) + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.String: + d.w.Write([]byte(strconv.Quote(v.String()))) + + case reflect.Interface: + // The only time we should get here is for nil interfaces due to + // unpackValue calls. + if v.IsNil() { + d.w.Write(nilAngleBytes) + } + + case reflect.Ptr: + // Do nothing. We should never get here since pointers have already + // been handled above. + + case reflect.Map: + // nil maps should be indicated as different than empty maps + if v.IsNil() { + d.w.Write(nilAngleBytes) + break + } + + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + numEntries := v.Len() + keys := v.MapKeys() + if d.cs.SortKeys { + sortValues(keys, d.cs) + } + for i, key := range keys { + d.dump(d.unpackValue(key)) + d.w.Write(colonSpaceBytes) + d.ignoreNextIndent = true + d.dump(d.unpackValue(v.MapIndex(key))) + if i < (numEntries - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.Struct: + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + vt := v.Type() + numFields := v.NumField() + for i := 0; i < numFields; i++ { + d.indent() + vtf := vt.Field(i) + d.w.Write([]byte(vtf.Name)) + d.w.Write(colonSpaceBytes) + d.ignoreNextIndent = true + d.dump(d.unpackValue(v.Field(i))) + if i < (numFields - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.Uintptr: + printHexPtr(d.w, uintptr(v.Uint())) + + case reflect.UnsafePointer, reflect.Chan, reflect.Func: + printHexPtr(d.w, v.Pointer()) + + // There were not any other types at the time this code was written, but + // fall back to letting the default fmt package handle it in case any new + // types are added. + default: + if v.CanInterface() { + fmt.Fprintf(d.w, "%v", v.Interface()) + } else { + fmt.Fprintf(d.w, "%v", v.String()) + } + } +} + +// fdump is a helper function to consolidate the logic from the various public +// methods which take varying writers and config states. +func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { + for _, arg := range a { + if arg == nil { + w.Write(interfaceBytes) + w.Write(spaceBytes) + w.Write(nilAngleBytes) + w.Write(newlineBytes) + continue + } + + d := dumpState{w: w, cs: cs} + d.pointers = make(map[uintptr]int) + d.dump(reflect.ValueOf(arg)) + d.w.Write(newlineBytes) + } +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func Fdump(w io.Writer, a ...interface{}) { + fdump(&Config, w, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as Dump. +func Sdump(a ...interface{}) string { + var buf bytes.Buffer + fdump(&Config, &buf, a...) + return buf.String() +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output + +The configuration options are controlled by an exported package global, +spew.Config. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to +get the formatted result as a string. +*/ +func Dump(a ...interface{}) { + fdump(&Config, os.Stdout, a...) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/davecgh/go-spew/spew/format.go new file mode 100644 index 0000000..ecf3b80 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/format.go @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2013 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" +) + +// supportedFlags is a list of all the character flags supported by fmt package. +const supportedFlags = "0-+# " + +// formatState implements the fmt.Formatter interface and contains information +// about the state of a formatting operation. The NewFormatter function can +// be used to get a new Formatter which can be used directly as arguments +// in standard fmt package printing calls. +type formatState struct { + value interface{} + fs fmt.State + depth int + pointers map[uintptr]int + ignoreNextType bool + cs *ConfigState +} + +// buildDefaultFormat recreates the original format string without precision +// and width information to pass in to fmt.Sprintf in the case of an +// unrecognized type. Unless new types are added to the language, this +// function won't ever be called. +func (f *formatState) buildDefaultFormat() (format string) { + buf := bytes.NewBuffer(percentBytes) + + for _, flag := range supportedFlags { + if f.fs.Flag(int(flag)) { + buf.WriteRune(flag) + } + } + + buf.WriteRune('v') + + format = buf.String() + return format +} + +// constructOrigFormat recreates the original format string including precision +// and width information to pass along to the standard fmt package. This allows +// automatic deferral of all format strings this package doesn't support. +func (f *formatState) constructOrigFormat(verb rune) (format string) { + buf := bytes.NewBuffer(percentBytes) + + for _, flag := range supportedFlags { + if f.fs.Flag(int(flag)) { + buf.WriteRune(flag) + } + } + + if width, ok := f.fs.Width(); ok { + buf.WriteString(strconv.Itoa(width)) + } + + if precision, ok := f.fs.Precision(); ok { + buf.Write(precisionBytes) + buf.WriteString(strconv.Itoa(precision)) + } + + buf.WriteRune(verb) + + format = buf.String() + return format +} + +// unpackValue returns values inside of non-nil interfaces when possible and +// ensures that types for values which have been unpacked from an interface +// are displayed when the show types flag is also set. +// This is useful for data types like structs, arrays, slices, and maps which +// can contain varying types packed inside an interface. +func (f *formatState) unpackValue(v reflect.Value) reflect.Value { + if v.Kind() == reflect.Interface { + f.ignoreNextType = false + if !v.IsNil() { + v = v.Elem() + } + } + return v +} + +// formatPtr handles formatting of pointers by indirecting them as necessary. +func (f *formatState) formatPtr(v reflect.Value) { + // Display nil if top level pointer is nil. + showTypes := f.fs.Flag('#') + if v.IsNil() && (!showTypes || f.ignoreNextType) { + f.fs.Write(nilAngleBytes) + return + } + + // Remove pointers at or below the current depth from map used to detect + // circular refs. + for k, depth := range f.pointers { + if depth >= f.depth { + delete(f.pointers, k) + } + } + + // Keep list of all dereferenced pointers to possibly show later. + pointerChain := make([]uintptr, 0) + + // Figure out how many levels of indirection there are by derferencing + // pointers and unpacking interfaces down the chain while detecting circular + // references. + nilFound := false + cycleFound := false + indirects := 0 + ve := v + for ve.Kind() == reflect.Ptr { + if ve.IsNil() { + nilFound = true + break + } + indirects++ + addr := ve.Pointer() + pointerChain = append(pointerChain, addr) + if pd, ok := f.pointers[addr]; ok && pd < f.depth { + cycleFound = true + indirects-- + break + } + f.pointers[addr] = f.depth + + ve = ve.Elem() + if ve.Kind() == reflect.Interface { + if ve.IsNil() { + nilFound = true + break + } + ve = ve.Elem() + } + } + + // Display type or indirection level depending on flags. + if showTypes && !f.ignoreNextType { + f.fs.Write(openParenBytes) + f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) + f.fs.Write([]byte(ve.Type().String())) + f.fs.Write(closeParenBytes) + } else { + if nilFound || cycleFound { + indirects += strings.Count(ve.Type().String(), "*") + } + f.fs.Write(openAngleBytes) + f.fs.Write([]byte(strings.Repeat("*", indirects))) + f.fs.Write(closeAngleBytes) + } + + // Display pointer information depending on flags. + if f.fs.Flag('+') && (len(pointerChain) > 0) { + f.fs.Write(openParenBytes) + for i, addr := range pointerChain { + if i > 0 { + f.fs.Write(pointerChainBytes) + } + printHexPtr(f.fs, addr) + } + f.fs.Write(closeParenBytes) + } + + // Display dereferenced value. + switch { + case nilFound == true: + f.fs.Write(nilAngleBytes) + + case cycleFound == true: + f.fs.Write(circularShortBytes) + + default: + f.ignoreNextType = true + f.format(ve) + } +} + +// format is the main workhorse for providing the Formatter interface. It +// uses the passed reflect value to figure out what kind of object we are +// dealing with and formats it appropriately. It is a recursive function, +// however circular data structures are detected and handled properly. +func (f *formatState) format(v reflect.Value) { + // Handle invalid reflect values immediately. + kind := v.Kind() + if kind == reflect.Invalid { + f.fs.Write(invalidAngleBytes) + return + } + + // Handle pointers specially. + if kind == reflect.Ptr { + f.formatPtr(v) + return + } + + // Print type information unless already handled elsewhere. + if !f.ignoreNextType && f.fs.Flag('#') { + f.fs.Write(openParenBytes) + f.fs.Write([]byte(v.Type().String())) + f.fs.Write(closeParenBytes) + } + f.ignoreNextType = false + + // Call Stringer/error interfaces if they exist and the handle methods + // flag is enabled. + if !f.cs.DisableMethods { + if (kind != reflect.Invalid) && (kind != reflect.Interface) { + if handled := handleMethods(f.cs, f.fs, v); handled { + return + } + } + } + + switch kind { + case reflect.Invalid: + // Do nothing. We should never get here since invalid has already + // been handled above. + + case reflect.Bool: + printBool(f.fs, v.Bool()) + + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + printInt(f.fs, v.Int(), 10) + + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + printUint(f.fs, v.Uint(), 10) + + case reflect.Float32: + printFloat(f.fs, v.Float(), 32) + + case reflect.Float64: + printFloat(f.fs, v.Float(), 64) + + case reflect.Complex64: + printComplex(f.fs, v.Complex(), 32) + + case reflect.Complex128: + printComplex(f.fs, v.Complex(), 64) + + case reflect.Slice: + if v.IsNil() { + f.fs.Write(nilAngleBytes) + break + } + fallthrough + + case reflect.Array: + f.fs.Write(openBracketBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + numEntries := v.Len() + for i := 0; i < numEntries; i++ { + if i > 0 { + f.fs.Write(spaceBytes) + } + f.ignoreNextType = true + f.format(f.unpackValue(v.Index(i))) + } + } + f.depth-- + f.fs.Write(closeBracketBytes) + + case reflect.String: + f.fs.Write([]byte(v.String())) + + case reflect.Interface: + // The only time we should get here is for nil interfaces due to + // unpackValue calls. + if v.IsNil() { + f.fs.Write(nilAngleBytes) + } + + case reflect.Ptr: + // Do nothing. We should never get here since pointers have already + // been handled above. + + case reflect.Map: + // nil maps should be indicated as different than empty maps + if v.IsNil() { + f.fs.Write(nilAngleBytes) + break + } + + f.fs.Write(openMapBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + keys := v.MapKeys() + if f.cs.SortKeys { + sortValues(keys, f.cs) + } + for i, key := range keys { + if i > 0 { + f.fs.Write(spaceBytes) + } + f.ignoreNextType = true + f.format(f.unpackValue(key)) + f.fs.Write(colonBytes) + f.ignoreNextType = true + f.format(f.unpackValue(v.MapIndex(key))) + } + } + f.depth-- + f.fs.Write(closeMapBytes) + + case reflect.Struct: + numFields := v.NumField() + f.fs.Write(openBraceBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + vt := v.Type() + for i := 0; i < numFields; i++ { + if i > 0 { + f.fs.Write(spaceBytes) + } + vtf := vt.Field(i) + if f.fs.Flag('+') || f.fs.Flag('#') { + f.fs.Write([]byte(vtf.Name)) + f.fs.Write(colonBytes) + } + f.format(f.unpackValue(v.Field(i))) + } + } + f.depth-- + f.fs.Write(closeBraceBytes) + + case reflect.Uintptr: + printHexPtr(f.fs, uintptr(v.Uint())) + + case reflect.UnsafePointer, reflect.Chan, reflect.Func: + printHexPtr(f.fs, v.Pointer()) + + // There were not any other types at the time this code was written, but + // fall back to letting the default fmt package handle it if any get added. + default: + format := f.buildDefaultFormat() + if v.CanInterface() { + fmt.Fprintf(f.fs, format, v.Interface()) + } else { + fmt.Fprintf(f.fs, format, v.String()) + } + } +} + +// Format satisfies the fmt.Formatter interface. See NewFormatter for usage +// details. +func (f *formatState) Format(fs fmt.State, verb rune) { + f.fs = fs + + // Use standard formatting for verbs that are not v. + if verb != 'v' { + format := f.constructOrigFormat(verb) + fmt.Fprintf(fs, format, f.value) + return + } + + if f.value == nil { + if fs.Flag('#') { + fs.Write(interfaceBytes) + } + fs.Write(nilAngleBytes) + return + } + + f.format(reflect.ValueOf(f.value)) +} + +// newFormatter is a helper function to consolidate the logic from the various +// public methods which take varying config states. +func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { + fs := &formatState{value: v, cs: cs} + fs.pointers = make(map[uintptr]int) + return fs +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +Printf, Println, or Fprintf. +*/ +func NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(&Config, v) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/spew.go b/vendor/github.com/davecgh/go-spew/spew/spew.go new file mode 100644 index 0000000..d8233f5 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/spew.go @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "fmt" + "io" +) + +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the formatted string as a value that satisfies error. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a default Formatter interface returned by NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) +func Print(a ...interface{}) (n int, err error) { + return fmt.Print(convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) +func Println(a ...interface{}) (n int, err error) { + return fmt.Println(convertArgs(a)...) +} + +// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprint(a ...interface{}) string { + return fmt.Sprint(convertArgs(a)...) +} + +// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, convertArgs(a)...) +} + +// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it +// were passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprintln(a ...interface{}) string { + return fmt.Sprintln(convertArgs(a)...) +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a default spew Formatter interface. +func convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = NewFormatter(arg) + } + return formatters +} diff --git a/vendor/github.com/gvalkov/golang-evdev/LICENSE b/vendor/github.com/gvalkov/golang-evdev/LICENSE new file mode 100644 index 0000000..fae43a2 --- /dev/null +++ b/vendor/github.com/gvalkov/golang-evdev/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2016 Georgi Valkov. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. 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. + + 3. Neither the name of author 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 GEORGI VALKOV 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. diff --git a/vendor/github.com/gvalkov/golang-evdev/Makefile b/vendor/github.com/gvalkov/golang-evdev/Makefile new file mode 100644 index 0000000..a768e70 --- /dev/null +++ b/vendor/github.com/gvalkov/golang-evdev/Makefile @@ -0,0 +1,9 @@ +all: ecodes.go + +HEADERS = /usr/include/linux/input.h +HEADERS += /usr/include/linux/input-event-codes.h + +ecodes.go: ecodes.go.template + ./bin/genecodes.py $(HEADERS) $< > $@ + +.PHONY: ecodes.go diff --git a/vendor/github.com/gvalkov/golang-evdev/README.rst b/vendor/github.com/gvalkov/golang-evdev/README.rst new file mode 100644 index 0000000..c66c29b --- /dev/null +++ b/vendor/github.com/gvalkov/golang-evdev/README.rst @@ -0,0 +1,13 @@ +*golang-evdev* +-------------- + +This package provides Go language bindings to the generic input event +interface in Linux. The *evdev* interface serves the purpose of +passing events generated in the kernel directly to userspace through +character devices that are typically located in `/dev/input/`. + +Documentation: + http://godoc.org/github.com/gvalkov/golang-evdev + +Development: + https://github.com/gvalkov/golang-evdev diff --git a/vendor/github.com/gvalkov/golang-evdev/_ioctl.go b/vendor/github.com/gvalkov/golang-evdev/_ioctl.go new file mode 100644 index 0000000..d28985d --- /dev/null +++ b/vendor/github.com/gvalkov/golang-evdev/_ioctl.go @@ -0,0 +1,50 @@ +package evdev + +// Bits and pieces from asm-generic/ioctl.h +import ( + "syscall" + "unsafe" +) + +const ( + _IOC_NONE = 0x0 + _IOC_WRITE = 0x1 + _IOC_READ = 0x2 + + _IOC_NRBITS = 8 + _IOC_TYPEBITS = 8 + _IOC_SIZEBITS = 14 + _IOC_DIRBITS = 2 + _IOC_NRSHIFT = 0 + + _IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS + _IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS + _IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS +) + +func _IOC(dir int, t int, nr int, size int) int { + return (dir << _IOC_DIRSHIFT) | (t << _IOC_TYPESHIFT) | + (nr << _IOC_NRSHIFT) | (size << _IOC_SIZESHIFT) +} + +func _IOR(t int, nr int, size int) int { + return _IOC(_IOC_READ, t, nr, size) +} + +func ioctl(fd uintptr, name int, data unsafe.Pointer) syscall.Errno { + _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, fd, uintptr(name), uintptr(data)) + return err +} + +// input.h ioctls +var _EVIOCGID = _IOR('E', 0x02, SizeofInputId) // 8 <- sizeof(struct input_id) +var _EVIOCGNAME = _IOC(_IOC_READ, 'E', 0x06, _MAX_NAME_SIZE) +var _EVIOCGPHYS = _IOC(_IOC_READ, 'E', 0x07, _MAX_NAME_SIZE) + +func _EVIOCGABS(ev int) int { + return _IOR('E', 0x40+ev, 24) // 24 <= sizeof(struct input_absinfo) +} + +func _EVIOCGBIT(ev, len int) int { + return _IOC(_IOC_READ, 'E', 0x20+ev, len) +} diff --git a/vendor/github.com/gvalkov/golang-evdev/cdefs.go b/vendor/github.com/gvalkov/golang-evdev/cdefs.go new file mode 100644 index 0000000..4872284 --- /dev/null +++ b/vendor/github.com/gvalkov/golang-evdev/cdefs.go @@ -0,0 +1,73 @@ +package evdev + +/* + #include + static int _EVIOCGNAME(int len) {return EVIOCGNAME(len);} + static int _EVIOCGPHYS(int len) {return EVIOCGPHYS(len);} + static int _EVIOCGUNIQ(int len) {return EVIOCGUNIQ(len);} + static int _EVIOCGPROP(int len) {return EVIOCGPROP(len);} + + static int _EVIOCGKEY(int len) {return EVIOCGKEY(len);} + static int _EVIOCGLED(int len) {return EVIOCGLED(len);} + static int _EVIOCGSND(int len) {return EVIOCGSND(len);} + static int _EVIOCGSW(int len) {return EVIOCGSW(len);} + + static int _EVIOCGBIT(int ev, int len) {return EVIOCGBIT(ev, len);} + static int _EVIOCGABS(int abs) {return EVIOCGABS(abs);} + static int _EVIOCSABS(int abs) {return EVIOCSABS(abs);} +*/ +import "C" +import "syscall" +import "unsafe" + +type _InputEvent C.struct_input_event +type _InputAbsinfo C.struct_input_absinfo +type _InputId C.struct_input_id +type _InputKeymapEntry C.struct_input_keymap_entry + +const ( + sizeofInputAbsinfo = C.sizeof_struct_input_absinfo + sizeofInputId = C.sizeof_struct_input_id + sizeofInputKeymapEntry = C.sizeof_struct_input_keymap_entry +) + +const MAX_NAME_SIZE = 256 + +const ( + EVIOCGID = C.EVIOCGID // get device ID + EVIOCGVERSION = C.EVIOCGVERSION // get driver version + EVIOCGREP = C.EVIOCGREP // get repeat settings + EVIOCSREP = C.EVIOCSREP // set repeat settings + + EVIOCGKEYCODE = C.EVIOCGKEYCODE // get keycode + EVIOCGKEYCODE_V2 = C.EVIOCGKEYCODE_V2 // get keycode + + EVIOCSKEYCODE = C.EVIOCSKEYCODE // set keycode + EVIOCSKEYCODE_V2 = C.EVIOCSKEYCODE_V2 // set keycode + + EVIOCSFF = C.EVIOCSFF // send a force effect to a force feedback device + EVIOCRMFF = C.EVIOCRMFF // erase a force effect + EVIOCGEFFECTS = C.EVIOCGEFFECTS // report number of effects playable at the same time + + EVIOCGRAB = C.EVIOCGRAB // grab/release device + EVIOCSCLOCKID = C.EVIOCSCLOCKID // set clockid to be used for timestamps +) + +var EVIOCGNAME = C._EVIOCGNAME(MAX_NAME_SIZE) // get device name +var EVIOCGPHYS = C._EVIOCGPHYS(MAX_NAME_SIZE) // get physical location +var EVIOCGUNIQ = C._EVIOCGUNIQ(MAX_NAME_SIZE) // get unique identifier +var EVIOCGPROP = C._EVIOCGPROP(MAX_NAME_SIZE) // get device properties + +var EVIOCGKEY = C._EVIOCGKEY(MAX_NAME_SIZE) // get global key state +var EVIOCGLED = C._EVIOCGLED(MAX_NAME_SIZE) // get all LEDs +var EVIOCGSND = C._EVIOCGSND(MAX_NAME_SIZE) // get all sounds status +var EVIOCGSW = C._EVIOCGSW(MAX_NAME_SIZE) // get all switch states + +func EVIOCGBIT(ev, l int) int { return int(C._EVIOCGBIT(C.int(ev), C.int(l))) } // get event bits +func EVIOCGABS(abs int) int { return int(C._EVIOCGABS(C.int(abs))) } // get abs bits +func EVIOCSABS(abs int) int { return int(C._EVIOCSABS(C.int(abs))) } // set abs bits + +func ioctl(fd uintptr, name uintptr, data unsafe.Pointer) syscall.Errno { + _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, fd, name, uintptr(data)) + return err +} diff --git a/vendor/github.com/gvalkov/golang-evdev/device.go b/vendor/github.com/gvalkov/golang-evdev/device.go new file mode 100644 index 0000000..5044f48 --- /dev/null +++ b/vendor/github.com/gvalkov/golang-evdev/device.go @@ -0,0 +1,307 @@ +// +build linux + +package evdev + +import ( + "bytes" + "encoding/binary" + "fmt" + "os" + "path/filepath" + "strings" + "unsafe" +) + +// A Linux input device from which events can be read. +type InputDevice struct { + Fn string // path to input device (devnode) + + Name string // device name + Phys string // physical topology of device + File *os.File // an open file handle to the input device + + Bustype uint16 // bus type identifier + Vendor uint16 // vendor identifier + Product uint16 // product identifier + Version uint16 // version identifier + + EvdevVersion int // evdev protocol version + + Capabilities map[CapabilityType][]CapabilityCode // supported event types and codes. + CapabilitiesFlat map[int][]int +} + +// Open an evdev input device. +func Open(devnode string) (*InputDevice, error) { + f, err := os.Open(devnode) + if err != nil { + return nil, err + } + + dev := InputDevice{} + dev.Fn = devnode + dev.File = f + + dev.set_device_info() + dev.set_device_capabilities() + + return &dev, nil +} + +// Read and return a slice of input events from device. +func (dev *InputDevice) Read() ([]InputEvent, error) { + events := make([]InputEvent, 16) + buffer := make([]byte, eventsize*16) + + _, err := dev.File.Read(buffer) + if err != nil { + return events, err + } + + b := bytes.NewBuffer(buffer) + err = binary.Read(b, binary.LittleEndian, &events) + if err != nil { + return events, err + } + + // remove trailing structures + for i := range events { + if events[i].Time.Sec == 0 { + events = append(events[:i]) + break + } + } + + return events, err +} + +// Read and return a single input event. +func (dev *InputDevice) ReadOne() (*InputEvent, error) { + event := InputEvent{} + buffer := make([]byte, eventsize) + + _, err := dev.File.Read(buffer) + if err != nil { + return &event, err + } + + b := bytes.NewBuffer(buffer) + err = binary.Read(b, binary.LittleEndian, &event) + if err != nil { + return &event, err + } + + return &event, err +} + +// Get a useful description for an input device. Example: +// InputDevice /dev/input/event3 (fd 3) +// name Logitech USB Laser Mouse +// phys usb-0000:00:12.0-2/input0 +// bus 0x3, vendor 0x46d, product 0xc069, version 0x110 +// events EV_KEY 1, EV_SYN 0, EV_REL 2, EV_MSC 4 +func (dev *InputDevice) String() string { + evtypes := make([]string, 0) + + for ev := range dev.Capabilities { + evtypes = append(evtypes, fmt.Sprintf("%s %d", ev.Name, ev.Type)) + } + evtypes_s := strings.Join(evtypes, ", ") + + return fmt.Sprintf( + "InputDevice %s (fd %d)\n"+ + " name %s\n"+ + " phys %s\n"+ + " bus 0x%04x, vendor 0x%04x, product 0x%04x, version 0x%04x\n"+ + " events %s", + dev.Fn, dev.File.Fd(), dev.Name, dev.Phys, dev.Bustype, + dev.Vendor, dev.Product, dev.Version, evtypes_s) +} + +// Gets the event types and event codes that the input device supports. +func (dev *InputDevice) set_device_capabilities() error { + // Capabilities is a map of supported event types to lists of + // events e.g: {1: [272, 273, 274, 275], 2: [0, 1, 6, 8]} + // capabilities := make(map[int][]int) + capabilities := make(map[CapabilityType][]CapabilityCode) + + evbits := new([(EV_MAX + 1) / 8]byte) + codebits := new([(KEY_MAX + 1) / 8]byte) + // absbits := new([6]byte) + + err := ioctl(dev.File.Fd(), uintptr(EVIOCGBIT(0, EV_MAX)), unsafe.Pointer(evbits)) + if err != 0 { + return err + } + + // Build a map of the device's capabilities + for evtype := 0; evtype < EV_MAX; evtype++ { + if evbits[evtype/8]&(1< 0 { + device_glob = device_glob_arg[0] + } + + fns, _ := ListInputDevicePaths(device_glob) + devices := make([]*InputDevice, 0) + + for i := range fns { + dev, err := Open(fns[i]) + if err == nil { + devices = append(devices, dev) + } + } + + return devices, nil +} + +func bytes_to_string(b *[MAX_NAME_SIZE]byte) string { + idx := bytes.IndexByte(b[:], 0) + return string(b[:idx]) +} diff --git a/vendor/github.com/gvalkov/golang-evdev/doc.go b/vendor/github.com/gvalkov/golang-evdev/doc.go new file mode 100644 index 0000000..2d80409 --- /dev/null +++ b/vendor/github.com/gvalkov/golang-evdev/doc.go @@ -0,0 +1,10 @@ +/* +This package provides bindings to the generic input event interface in +Linux. The evdev interface serves the purpose of passing events +generated in the kernel directly to userspace through character +devices that are typically located in /dev/input/. + +Please refer to the godoc examples and the bin/evtest example program. + +*/ +package evdev diff --git a/vendor/github.com/gvalkov/golang-evdev/ecodes.go b/vendor/github.com/gvalkov/golang-evdev/ecodes.go new file mode 100644 index 0000000..4bdeb7e --- /dev/null +++ b/vendor/github.com/gvalkov/golang-evdev/ecodes.go @@ -0,0 +1,1537 @@ +// -*- mode: go; -*- + +// Integer constants defined in linux/input.h and linux/input-event-codes.h can be accessed +// directly as constants or through the provided reverse and forward mappings: + +// +// evdev.KEY_A // 30 +// evdev.ecodes["KEY_A"] // 30 +// evdev.KEY[30] // "KEY_A" +// evdev.REL[0] // "REL_X" +// evdev.EV[evdev.EV_KEY] // "EV_KEY" +// evdev.ByEventType[EV_REL][0] // "REL_X" +// +// Generated on: Linux 4.7.4-200.fc24.x86_64 #1 SMP Thu Sep 15 18:42:09 UTC 2016 x86_64 + +package evdev + +import "strings" + +const ( + EV_VERSION = 0x010001 + ID_BUS = 0 + ID_VENDOR = 1 + ID_PRODUCT = 2 + ID_VERSION = 3 + BUS_PCI = 0x01 + BUS_ISAPNP = 0x02 + BUS_USB = 0x03 + BUS_HIL = 0x04 + BUS_BLUETOOTH = 0x05 + BUS_VIRTUAL = 0x06 + BUS_ISA = 0x10 + BUS_I8042 = 0x11 + BUS_XTKBD = 0x12 + BUS_RS232 = 0x13 + BUS_GAMEPORT = 0x14 + BUS_PARPORT = 0x15 + BUS_AMIGA = 0x16 + BUS_ADB = 0x17 + BUS_I2C = 0x18 + BUS_HOST = 0x19 + BUS_GSC = 0x1A + BUS_ATARI = 0x1B + BUS_SPI = 0x1C + BUS_RMI = 0x1D + BUS_CEC = 0x1E + FF_STATUS_STOPPED = 0x00 + FF_STATUS_PLAYING = 0x01 + FF_STATUS_MAX = 0x01 + FF_RUMBLE = 0x50 + FF_PERIODIC = 0x51 + FF_CONSTANT = 0x52 + FF_SPRING = 0x53 + FF_FRICTION = 0x54 + FF_DAMPER = 0x55 + FF_INERTIA = 0x56 + FF_RAMP = 0x57 + FF_EFFECT_MIN = FF_RUMBLE + FF_EFFECT_MAX = FF_RAMP + FF_SQUARE = 0x58 + FF_TRIANGLE = 0x59 + FF_SINE = 0x5a + FF_SAW_UP = 0x5b + FF_SAW_DOWN = 0x5c + FF_CUSTOM = 0x5d + FF_WAVEFORM_MIN = FF_SQUARE + FF_WAVEFORM_MAX = FF_CUSTOM + FF_GAIN = 0x60 + FF_AUTOCENTER = 0x61 + FF_MAX_EFFECTS = FF_GAIN + FF_MAX = 0x7f + EV_SYN = 0x00 + EV_KEY = 0x01 + EV_REL = 0x02 + EV_ABS = 0x03 + EV_MSC = 0x04 + EV_SW = 0x05 + EV_LED = 0x11 + EV_SND = 0x12 + EV_REP = 0x14 + EV_FF = 0x15 + EV_PWR = 0x16 + EV_FF_STATUS = 0x17 + EV_MAX = 0x1f + SYN_REPORT = 0 + SYN_CONFIG = 1 + SYN_MT_REPORT = 2 + SYN_DROPPED = 3 + SYN_MAX = 0xf + KEY_RESERVED = 0 + KEY_ESC = 1 + KEY_1 = 2 + KEY_2 = 3 + KEY_3 = 4 + KEY_4 = 5 + KEY_5 = 6 + KEY_6 = 7 + KEY_7 = 8 + KEY_8 = 9 + KEY_9 = 10 + KEY_0 = 11 + KEY_MINUS = 12 + KEY_EQUAL = 13 + KEY_BACKSPACE = 14 + KEY_TAB = 15 + KEY_Q = 16 + KEY_W = 17 + KEY_E = 18 + KEY_R = 19 + KEY_T = 20 + KEY_Y = 21 + KEY_U = 22 + KEY_I = 23 + KEY_O = 24 + KEY_P = 25 + KEY_LEFTBRACE = 26 + KEY_RIGHTBRACE = 27 + KEY_ENTER = 28 + KEY_LEFTCTRL = 29 + KEY_A = 30 + KEY_S = 31 + KEY_D = 32 + KEY_F = 33 + KEY_G = 34 + KEY_H = 35 + KEY_J = 36 + KEY_K = 37 + KEY_L = 38 + KEY_SEMICOLON = 39 + KEY_APOSTROPHE = 40 + KEY_GRAVE = 41 + KEY_LEFTSHIFT = 42 + KEY_BACKSLASH = 43 + KEY_Z = 44 + KEY_X = 45 + KEY_C = 46 + KEY_V = 47 + KEY_B = 48 + KEY_N = 49 + KEY_M = 50 + KEY_COMMA = 51 + KEY_DOT = 52 + KEY_SLASH = 53 + KEY_RIGHTSHIFT = 54 + KEY_KPASTERISK = 55 + KEY_LEFTALT = 56 + KEY_SPACE = 57 + KEY_CAPSLOCK = 58 + KEY_F1 = 59 + KEY_F2 = 60 + KEY_F3 = 61 + KEY_F4 = 62 + KEY_F5 = 63 + KEY_F6 = 64 + KEY_F7 = 65 + KEY_F8 = 66 + KEY_F9 = 67 + KEY_F10 = 68 + KEY_NUMLOCK = 69 + KEY_SCROLLLOCK = 70 + KEY_KP7 = 71 + KEY_KP8 = 72 + KEY_KP9 = 73 + KEY_KPMINUS = 74 + KEY_KP4 = 75 + KEY_KP5 = 76 + KEY_KP6 = 77 + KEY_KPPLUS = 78 + KEY_KP1 = 79 + KEY_KP2 = 80 + KEY_KP3 = 81 + KEY_KP0 = 82 + KEY_KPDOT = 83 + KEY_ZENKAKUHANKAKU = 85 + KEY_102ND = 86 + KEY_F11 = 87 + KEY_F12 = 88 + KEY_RO = 89 + KEY_KATAKANA = 90 + KEY_HIRAGANA = 91 + KEY_HENKAN = 92 + KEY_KATAKANAHIRAGANA = 93 + KEY_MUHENKAN = 94 + KEY_KPJPCOMMA = 95 + KEY_KPENTER = 96 + KEY_RIGHTCTRL = 97 + KEY_KPSLASH = 98 + KEY_SYSRQ = 99 + KEY_RIGHTALT = 100 + KEY_LINEFEED = 101 + KEY_HOME = 102 + KEY_UP = 103 + KEY_PAGEUP = 104 + KEY_LEFT = 105 + KEY_RIGHT = 106 + KEY_END = 107 + KEY_DOWN = 108 + KEY_PAGEDOWN = 109 + KEY_INSERT = 110 + KEY_DELETE = 111 + KEY_MACRO = 112 + KEY_MUTE = 113 + KEY_VOLUMEDOWN = 114 + KEY_VOLUMEUP = 115 + KEY_POWER = 116 + KEY_KPEQUAL = 117 + KEY_KPPLUSMINUS = 118 + KEY_PAUSE = 119 + KEY_SCALE = 120 + KEY_KPCOMMA = 121 + KEY_HANGEUL = 122 + KEY_HANGUEL = KEY_HANGEUL + KEY_HANJA = 123 + KEY_YEN = 124 + KEY_LEFTMETA = 125 + KEY_RIGHTMETA = 126 + KEY_COMPOSE = 127 + KEY_STOP = 128 + KEY_AGAIN = 129 + KEY_PROPS = 130 + KEY_UNDO = 131 + KEY_FRONT = 132 + KEY_COPY = 133 + KEY_OPEN = 134 + KEY_PASTE = 135 + KEY_FIND = 136 + KEY_CUT = 137 + KEY_HELP = 138 + KEY_MENU = 139 + KEY_CALC = 140 + KEY_SETUP = 141 + KEY_SLEEP = 142 + KEY_WAKEUP = 143 + KEY_FILE = 144 + KEY_SENDFILE = 145 + KEY_DELETEFILE = 146 + KEY_XFER = 147 + KEY_PROG1 = 148 + KEY_PROG2 = 149 + KEY_WWW = 150 + KEY_MSDOS = 151 + KEY_COFFEE = 152 + KEY_SCREENLOCK = KEY_COFFEE + KEY_ROTATE_DISPLAY = 153 + KEY_DIRECTION = KEY_ROTATE_DISPLAY + KEY_CYCLEWINDOWS = 154 + KEY_MAIL = 155 + KEY_BOOKMARKS = 156 + KEY_COMPUTER = 157 + KEY_BACK = 158 + KEY_FORWARD = 159 + KEY_CLOSECD = 160 + KEY_EJECTCD = 161 + KEY_EJECTCLOSECD = 162 + KEY_NEXTSONG = 163 + KEY_PLAYPAUSE = 164 + KEY_PREVIOUSSONG = 165 + KEY_STOPCD = 166 + KEY_RECORD = 167 + KEY_REWIND = 168 + KEY_PHONE = 169 + KEY_ISO = 170 + KEY_CONFIG = 171 + KEY_HOMEPAGE = 172 + KEY_REFRESH = 173 + KEY_EXIT = 174 + KEY_MOVE = 175 + KEY_EDIT = 176 + KEY_SCROLLUP = 177 + KEY_SCROLLDOWN = 178 + KEY_KPLEFTPAREN = 179 + KEY_KPRIGHTPAREN = 180 + KEY_NEW = 181 + KEY_REDO = 182 + KEY_F13 = 183 + KEY_F14 = 184 + KEY_F15 = 185 + KEY_F16 = 186 + KEY_F17 = 187 + KEY_F18 = 188 + KEY_F19 = 189 + KEY_F20 = 190 + KEY_F21 = 191 + KEY_F22 = 192 + KEY_F23 = 193 + KEY_F24 = 194 + KEY_PLAYCD = 200 + KEY_PAUSECD = 201 + KEY_PROG3 = 202 + KEY_PROG4 = 203 + KEY_DASHBOARD = 204 + KEY_SUSPEND = 205 + KEY_CLOSE = 206 + KEY_PLAY = 207 + KEY_FASTFORWARD = 208 + KEY_BASSBOOST = 209 + KEY_PRINT = 210 + KEY_HP = 211 + KEY_CAMERA = 212 + KEY_SOUND = 213 + KEY_QUESTION = 214 + KEY_EMAIL = 215 + KEY_CHAT = 216 + KEY_SEARCH = 217 + KEY_CONNECT = 218 + KEY_FINANCE = 219 + KEY_SPORT = 220 + KEY_SHOP = 221 + KEY_ALTERASE = 222 + KEY_CANCEL = 223 + KEY_BRIGHTNESSDOWN = 224 + KEY_BRIGHTNESSUP = 225 + KEY_MEDIA = 226 + KEY_SWITCHVIDEOMODE = 227 + KEY_KBDILLUMTOGGLE = 228 + KEY_KBDILLUMDOWN = 229 + KEY_KBDILLUMUP = 230 + KEY_SEND = 231 + KEY_REPLY = 232 + KEY_FORWARDMAIL = 233 + KEY_SAVE = 234 + KEY_DOCUMENTS = 235 + KEY_BATTERY = 236 + KEY_BLUETOOTH = 237 + KEY_WLAN = 238 + KEY_UWB = 239 + KEY_UNKNOWN = 240 + KEY_VIDEO_NEXT = 241 + KEY_VIDEO_PREV = 242 + KEY_BRIGHTNESS_CYCLE = 243 + KEY_BRIGHTNESS_AUTO = 244 + KEY_BRIGHTNESS_ZERO = KEY_BRIGHTNESS_AUTO + KEY_DISPLAY_OFF = 245 + KEY_WWAN = 246 + KEY_WIMAX = KEY_WWAN + KEY_RFKILL = 247 + KEY_MICMUTE = 248 + BTN_MISC = 0x100 + BTN_0 = 0x100 + BTN_1 = 0x101 + BTN_2 = 0x102 + BTN_3 = 0x103 + BTN_4 = 0x104 + BTN_5 = 0x105 + BTN_6 = 0x106 + BTN_7 = 0x107 + BTN_8 = 0x108 + BTN_9 = 0x109 + BTN_MOUSE = 0x110 + BTN_LEFT = 0x110 + BTN_RIGHT = 0x111 + BTN_MIDDLE = 0x112 + BTN_SIDE = 0x113 + BTN_EXTRA = 0x114 + BTN_FORWARD = 0x115 + BTN_BACK = 0x116 + BTN_TASK = 0x117 + BTN_JOYSTICK = 0x120 + BTN_TRIGGER = 0x120 + BTN_THUMB = 0x121 + BTN_THUMB2 = 0x122 + BTN_TOP = 0x123 + BTN_TOP2 = 0x124 + BTN_PINKIE = 0x125 + BTN_BASE = 0x126 + BTN_BASE2 = 0x127 + BTN_BASE3 = 0x128 + BTN_BASE4 = 0x129 + BTN_BASE5 = 0x12a + BTN_BASE6 = 0x12b + BTN_DEAD = 0x12f + BTN_GAMEPAD = 0x130 + BTN_SOUTH = 0x130 + BTN_A = BTN_SOUTH + BTN_EAST = 0x131 + BTN_B = BTN_EAST + BTN_C = 0x132 + BTN_NORTH = 0x133 + BTN_X = BTN_NORTH + BTN_WEST = 0x134 + BTN_Y = BTN_WEST + BTN_Z = 0x135 + BTN_TL = 0x136 + BTN_TR = 0x137 + BTN_TL2 = 0x138 + BTN_TR2 = 0x139 + BTN_SELECT = 0x13a + BTN_START = 0x13b + BTN_MODE = 0x13c + BTN_THUMBL = 0x13d + BTN_THUMBR = 0x13e + BTN_DIGI = 0x140 + BTN_TOOL_PEN = 0x140 + BTN_TOOL_RUBBER = 0x141 + BTN_TOOL_BRUSH = 0x142 + BTN_TOOL_PENCIL = 0x143 + BTN_TOOL_AIRBRUSH = 0x144 + BTN_TOOL_FINGER = 0x145 + BTN_TOOL_MOUSE = 0x146 + BTN_TOOL_LENS = 0x147 + BTN_TOOL_QUINTTAP = 0x148 + BTN_TOUCH = 0x14a + BTN_STYLUS = 0x14b + BTN_STYLUS2 = 0x14c + BTN_TOOL_DOUBLETAP = 0x14d + BTN_TOOL_TRIPLETAP = 0x14e + BTN_TOOL_QUADTAP = 0x14f + BTN_WHEEL = 0x150 + BTN_GEAR_DOWN = 0x150 + BTN_GEAR_UP = 0x151 + KEY_OK = 0x160 + KEY_SELECT = 0x161 + KEY_GOTO = 0x162 + KEY_CLEAR = 0x163 + KEY_POWER2 = 0x164 + KEY_OPTION = 0x165 + KEY_INFO = 0x166 + KEY_TIME = 0x167 + KEY_VENDOR = 0x168 + KEY_ARCHIVE = 0x169 + KEY_PROGRAM = 0x16a + KEY_CHANNEL = 0x16b + KEY_FAVORITES = 0x16c + KEY_EPG = 0x16d + KEY_PVR = 0x16e + KEY_MHP = 0x16f + KEY_LANGUAGE = 0x170 + KEY_TITLE = 0x171 + KEY_SUBTITLE = 0x172 + KEY_ANGLE = 0x173 + KEY_ZOOM = 0x174 + KEY_MODE = 0x175 + KEY_KEYBOARD = 0x176 + KEY_SCREEN = 0x177 + KEY_PC = 0x178 + KEY_TV = 0x179 + KEY_TV2 = 0x17a + KEY_VCR = 0x17b + KEY_VCR2 = 0x17c + KEY_SAT = 0x17d + KEY_SAT2 = 0x17e + KEY_CD = 0x17f + KEY_TAPE = 0x180 + KEY_RADIO = 0x181 + KEY_TUNER = 0x182 + KEY_PLAYER = 0x183 + KEY_TEXT = 0x184 + KEY_DVD = 0x185 + KEY_AUX = 0x186 + KEY_MP3 = 0x187 + KEY_AUDIO = 0x188 + KEY_VIDEO = 0x189 + KEY_DIRECTORY = 0x18a + KEY_LIST = 0x18b + KEY_MEMO = 0x18c + KEY_CALENDAR = 0x18d + KEY_RED = 0x18e + KEY_GREEN = 0x18f + KEY_YELLOW = 0x190 + KEY_BLUE = 0x191 + KEY_CHANNELUP = 0x192 + KEY_CHANNELDOWN = 0x193 + KEY_FIRST = 0x194 + KEY_LAST = 0x195 + KEY_AB = 0x196 + KEY_NEXT = 0x197 + KEY_RESTART = 0x198 + KEY_SLOW = 0x199 + KEY_SHUFFLE = 0x19a + KEY_BREAK = 0x19b + KEY_PREVIOUS = 0x19c + KEY_DIGITS = 0x19d + KEY_TEEN = 0x19e + KEY_TWEN = 0x19f + KEY_VIDEOPHONE = 0x1a0 + KEY_GAMES = 0x1a1 + KEY_ZOOMIN = 0x1a2 + KEY_ZOOMOUT = 0x1a3 + KEY_ZOOMRESET = 0x1a4 + KEY_WORDPROCESSOR = 0x1a5 + KEY_EDITOR = 0x1a6 + KEY_SPREADSHEET = 0x1a7 + KEY_GRAPHICSEDITOR = 0x1a8 + KEY_PRESENTATION = 0x1a9 + KEY_DATABASE = 0x1aa + KEY_NEWS = 0x1ab + KEY_VOICEMAIL = 0x1ac + KEY_ADDRESSBOOK = 0x1ad + KEY_MESSENGER = 0x1ae + KEY_DISPLAYTOGGLE = 0x1af + KEY_BRIGHTNESS_TOGGLE = KEY_DISPLAYTOGGLE + KEY_SPELLCHECK = 0x1b0 + KEY_LOGOFF = 0x1b1 + KEY_DOLLAR = 0x1b2 + KEY_EURO = 0x1b3 + KEY_FRAMEBACK = 0x1b4 + KEY_FRAMEFORWARD = 0x1b5 + KEY_CONTEXT_MENU = 0x1b6 + KEY_MEDIA_REPEAT = 0x1b7 + KEY_10CHANNELSUP = 0x1b8 + KEY_10CHANNELSDOWN = 0x1b9 + KEY_IMAGES = 0x1ba + KEY_DEL_EOL = 0x1c0 + KEY_DEL_EOS = 0x1c1 + KEY_INS_LINE = 0x1c2 + KEY_DEL_LINE = 0x1c3 + KEY_FN = 0x1d0 + KEY_FN_ESC = 0x1d1 + KEY_FN_F1 = 0x1d2 + KEY_FN_F2 = 0x1d3 + KEY_FN_F3 = 0x1d4 + KEY_FN_F4 = 0x1d5 + KEY_FN_F5 = 0x1d6 + KEY_FN_F6 = 0x1d7 + KEY_FN_F7 = 0x1d8 + KEY_FN_F8 = 0x1d9 + KEY_FN_F9 = 0x1da + KEY_FN_F10 = 0x1db + KEY_FN_F11 = 0x1dc + KEY_FN_F12 = 0x1dd + KEY_FN_1 = 0x1de + KEY_FN_2 = 0x1df + KEY_FN_D = 0x1e0 + KEY_FN_E = 0x1e1 + KEY_FN_F = 0x1e2 + KEY_FN_S = 0x1e3 + KEY_FN_B = 0x1e4 + KEY_BRL_DOT1 = 0x1f1 + KEY_BRL_DOT2 = 0x1f2 + KEY_BRL_DOT3 = 0x1f3 + KEY_BRL_DOT4 = 0x1f4 + KEY_BRL_DOT5 = 0x1f5 + KEY_BRL_DOT6 = 0x1f6 + KEY_BRL_DOT7 = 0x1f7 + KEY_BRL_DOT8 = 0x1f8 + KEY_BRL_DOT9 = 0x1f9 + KEY_BRL_DOT10 = 0x1fa + KEY_NUMERIC_0 = 0x200 + KEY_NUMERIC_1 = 0x201 + KEY_NUMERIC_2 = 0x202 + KEY_NUMERIC_3 = 0x203 + KEY_NUMERIC_4 = 0x204 + KEY_NUMERIC_5 = 0x205 + KEY_NUMERIC_6 = 0x206 + KEY_NUMERIC_7 = 0x207 + KEY_NUMERIC_8 = 0x208 + KEY_NUMERIC_9 = 0x209 + KEY_NUMERIC_STAR = 0x20a + KEY_NUMERIC_POUND = 0x20b + KEY_NUMERIC_A = 0x20c + KEY_NUMERIC_B = 0x20d + KEY_NUMERIC_C = 0x20e + KEY_NUMERIC_D = 0x20f + KEY_CAMERA_FOCUS = 0x210 + KEY_WPS_BUTTON = 0x211 + KEY_TOUCHPAD_TOGGLE = 0x212 + KEY_TOUCHPAD_ON = 0x213 + KEY_TOUCHPAD_OFF = 0x214 + KEY_CAMERA_ZOOMIN = 0x215 + KEY_CAMERA_ZOOMOUT = 0x216 + KEY_CAMERA_UP = 0x217 + KEY_CAMERA_DOWN = 0x218 + KEY_CAMERA_LEFT = 0x219 + KEY_CAMERA_RIGHT = 0x21a + KEY_ATTENDANT_ON = 0x21b + KEY_ATTENDANT_OFF = 0x21c + KEY_ATTENDANT_TOGGLE = 0x21d + KEY_LIGHTS_TOGGLE = 0x21e + BTN_DPAD_UP = 0x220 + BTN_DPAD_DOWN = 0x221 + BTN_DPAD_LEFT = 0x222 + BTN_DPAD_RIGHT = 0x223 + KEY_ALS_TOGGLE = 0x230 + KEY_BUTTONCONFIG = 0x240 + KEY_TASKMANAGER = 0x241 + KEY_JOURNAL = 0x242 + KEY_CONTROLPANEL = 0x243 + KEY_APPSELECT = 0x244 + KEY_SCREENSAVER = 0x245 + KEY_VOICECOMMAND = 0x246 + KEY_BRIGHTNESS_MIN = 0x250 + KEY_BRIGHTNESS_MAX = 0x251 + KEY_KBDINPUTASSIST_PREV = 0x260 + KEY_KBDINPUTASSIST_NEXT = 0x261 + KEY_KBDINPUTASSIST_PREVGROUP = 0x262 + KEY_KBDINPUTASSIST_NEXTGROUP = 0x263 + KEY_KBDINPUTASSIST_ACCEPT = 0x264 + KEY_KBDINPUTASSIST_CANCEL = 0x265 + KEY_RIGHT_UP = 0x266 + KEY_RIGHT_DOWN = 0x267 + KEY_LEFT_UP = 0x268 + KEY_LEFT_DOWN = 0x269 + KEY_ROOT_MENU = 0x26a + KEY_MEDIA_TOP_MENU = 0x26b + KEY_NUMERIC_11 = 0x26c + KEY_NUMERIC_12 = 0x26d + KEY_AUDIO_DESC = 0x26e + KEY_3D_MODE = 0x26f + KEY_NEXT_FAVORITE = 0x270 + KEY_STOP_RECORD = 0x271 + KEY_PAUSE_RECORD = 0x272 + KEY_VOD = 0x273 + KEY_UNMUTE = 0x274 + KEY_FASTREVERSE = 0x275 + KEY_SLOWREVERSE = 0x276 + KEY_DATA = 0x275 + BTN_TRIGGER_HAPPY = 0x2c0 + BTN_TRIGGER_HAPPY1 = 0x2c0 + BTN_TRIGGER_HAPPY2 = 0x2c1 + BTN_TRIGGER_HAPPY3 = 0x2c2 + BTN_TRIGGER_HAPPY4 = 0x2c3 + BTN_TRIGGER_HAPPY5 = 0x2c4 + BTN_TRIGGER_HAPPY6 = 0x2c5 + BTN_TRIGGER_HAPPY7 = 0x2c6 + BTN_TRIGGER_HAPPY8 = 0x2c7 + BTN_TRIGGER_HAPPY9 = 0x2c8 + BTN_TRIGGER_HAPPY10 = 0x2c9 + BTN_TRIGGER_HAPPY11 = 0x2ca + BTN_TRIGGER_HAPPY12 = 0x2cb + BTN_TRIGGER_HAPPY13 = 0x2cc + BTN_TRIGGER_HAPPY14 = 0x2cd + BTN_TRIGGER_HAPPY15 = 0x2ce + BTN_TRIGGER_HAPPY16 = 0x2cf + BTN_TRIGGER_HAPPY17 = 0x2d0 + BTN_TRIGGER_HAPPY18 = 0x2d1 + BTN_TRIGGER_HAPPY19 = 0x2d2 + BTN_TRIGGER_HAPPY20 = 0x2d3 + BTN_TRIGGER_HAPPY21 = 0x2d4 + BTN_TRIGGER_HAPPY22 = 0x2d5 + BTN_TRIGGER_HAPPY23 = 0x2d6 + BTN_TRIGGER_HAPPY24 = 0x2d7 + BTN_TRIGGER_HAPPY25 = 0x2d8 + BTN_TRIGGER_HAPPY26 = 0x2d9 + BTN_TRIGGER_HAPPY27 = 0x2da + BTN_TRIGGER_HAPPY28 = 0x2db + BTN_TRIGGER_HAPPY29 = 0x2dc + BTN_TRIGGER_HAPPY30 = 0x2dd + BTN_TRIGGER_HAPPY31 = 0x2de + BTN_TRIGGER_HAPPY32 = 0x2df + BTN_TRIGGER_HAPPY33 = 0x2e0 + BTN_TRIGGER_HAPPY34 = 0x2e1 + BTN_TRIGGER_HAPPY35 = 0x2e2 + BTN_TRIGGER_HAPPY36 = 0x2e3 + BTN_TRIGGER_HAPPY37 = 0x2e4 + BTN_TRIGGER_HAPPY38 = 0x2e5 + BTN_TRIGGER_HAPPY39 = 0x2e6 + BTN_TRIGGER_HAPPY40 = 0x2e7 + KEY_MIN_INTERESTING = KEY_MUTE + KEY_MAX = 0x2ff + REL_X = 0x00 + REL_Y = 0x01 + REL_Z = 0x02 + REL_RX = 0x03 + REL_RY = 0x04 + REL_RZ = 0x05 + REL_HWHEEL = 0x06 + REL_DIAL = 0x07 + REL_WHEEL = 0x08 + REL_MISC = 0x09 + REL_MAX = 0x0f + ABS_X = 0x00 + ABS_Y = 0x01 + ABS_Z = 0x02 + ABS_RX = 0x03 + ABS_RY = 0x04 + ABS_RZ = 0x05 + ABS_THROTTLE = 0x06 + ABS_RUDDER = 0x07 + ABS_WHEEL = 0x08 + ABS_GAS = 0x09 + ABS_BRAKE = 0x0a + ABS_HAT0X = 0x10 + ABS_HAT0Y = 0x11 + ABS_HAT1X = 0x12 + ABS_HAT1Y = 0x13 + ABS_HAT2X = 0x14 + ABS_HAT2Y = 0x15 + ABS_HAT3X = 0x16 + ABS_HAT3Y = 0x17 + ABS_PRESSURE = 0x18 + ABS_DISTANCE = 0x19 + ABS_TILT_X = 0x1a + ABS_TILT_Y = 0x1b + ABS_TOOL_WIDTH = 0x1c + ABS_VOLUME = 0x20 + ABS_MISC = 0x28 + ABS_MT_SLOT = 0x2f + ABS_MT_TOUCH_MAJOR = 0x30 + ABS_MT_TOUCH_MINOR = 0x31 + ABS_MT_WIDTH_MAJOR = 0x32 + ABS_MT_WIDTH_MINOR = 0x33 + ABS_MT_ORIENTATION = 0x34 + ABS_MT_POSITION_X = 0x35 + ABS_MT_POSITION_Y = 0x36 + ABS_MT_TOOL_TYPE = 0x37 + ABS_MT_BLOB_ID = 0x38 + ABS_MT_TRACKING_ID = 0x39 + ABS_MT_PRESSURE = 0x3a + ABS_MT_DISTANCE = 0x3b + ABS_MT_TOOL_X = 0x3c + ABS_MT_TOOL_Y = 0x3d + ABS_MAX = 0x3f + SW_LID = 0x00 + SW_TABLET_MODE = 0x01 + SW_HEADPHONE_INSERT = 0x02 + SW_RFKILL_ALL = 0x03 + SW_RADIO = SW_RFKILL_ALL + SW_MICROPHONE_INSERT = 0x04 + SW_DOCK = 0x05 + SW_LINEOUT_INSERT = 0x06 + SW_JACK_PHYSICAL_INSERT = 0x07 + SW_VIDEOOUT_INSERT = 0x08 + SW_CAMERA_LENS_COVER = 0x09 + SW_KEYPAD_SLIDE = 0x0a + SW_FRONT_PROXIMITY = 0x0b + SW_ROTATE_LOCK = 0x0c + SW_LINEIN_INSERT = 0x0d + SW_MUTE_DEVICE = 0x0e + SW_PEN_INSERTED = 0x0f + SW_MAX = 0x0f + MSC_SERIAL = 0x00 + MSC_PULSELED = 0x01 + MSC_GESTURE = 0x02 + MSC_RAW = 0x03 + MSC_SCAN = 0x04 + MSC_TIMESTAMP = 0x05 + MSC_MAX = 0x07 + LED_NUML = 0x00 + LED_CAPSL = 0x01 + LED_SCROLLL = 0x02 + LED_COMPOSE = 0x03 + LED_KANA = 0x04 + LED_SLEEP = 0x05 + LED_SUSPEND = 0x06 + LED_MUTE = 0x07 + LED_MISC = 0x08 + LED_MAIL = 0x09 + LED_CHARGING = 0x0a + LED_MAX = 0x0f + REP_DELAY = 0x00 + REP_PERIOD = 0x01 + REP_MAX = 0x01 + SND_CLICK = 0x00 + SND_BELL = 0x01 + SND_TONE = 0x02 + SND_MAX = 0x07 +) + +var ecodes = map[string]int{ + "EV_VERSION": EV_VERSION, + "ID_BUS": ID_BUS, + "ID_VENDOR": ID_VENDOR, + "ID_PRODUCT": ID_PRODUCT, + "ID_VERSION": ID_VERSION, + "BUS_PCI": BUS_PCI, + "BUS_ISAPNP": BUS_ISAPNP, + "BUS_USB": BUS_USB, + "BUS_HIL": BUS_HIL, + "BUS_BLUETOOTH": BUS_BLUETOOTH, + "BUS_VIRTUAL": BUS_VIRTUAL, + "BUS_ISA": BUS_ISA, + "BUS_I8042": BUS_I8042, + "BUS_XTKBD": BUS_XTKBD, + "BUS_RS232": BUS_RS232, + "BUS_GAMEPORT": BUS_GAMEPORT, + "BUS_PARPORT": BUS_PARPORT, + "BUS_AMIGA": BUS_AMIGA, + "BUS_ADB": BUS_ADB, + "BUS_I2C": BUS_I2C, + "BUS_HOST": BUS_HOST, + "BUS_GSC": BUS_GSC, + "BUS_ATARI": BUS_ATARI, + "BUS_SPI": BUS_SPI, + "BUS_RMI": BUS_RMI, + "BUS_CEC": BUS_CEC, + "FF_STATUS_STOPPED": FF_STATUS_STOPPED, + "FF_STATUS_PLAYING": FF_STATUS_PLAYING, + "FF_STATUS_MAX": FF_STATUS_MAX, + "FF_RUMBLE": FF_RUMBLE, + "FF_PERIODIC": FF_PERIODIC, + "FF_CONSTANT": FF_CONSTANT, + "FF_SPRING": FF_SPRING, + "FF_FRICTION": FF_FRICTION, + "FF_DAMPER": FF_DAMPER, + "FF_INERTIA": FF_INERTIA, + "FF_RAMP": FF_RAMP, + "FF_EFFECT_MIN": FF_EFFECT_MIN, + "FF_EFFECT_MAX": FF_EFFECT_MAX, + "FF_SQUARE": FF_SQUARE, + "FF_TRIANGLE": FF_TRIANGLE, + "FF_SINE": FF_SINE, + "FF_SAW_UP": FF_SAW_UP, + "FF_SAW_DOWN": FF_SAW_DOWN, + "FF_CUSTOM": FF_CUSTOM, + "FF_WAVEFORM_MIN": FF_WAVEFORM_MIN, + "FF_WAVEFORM_MAX": FF_WAVEFORM_MAX, + "FF_GAIN": FF_GAIN, + "FF_AUTOCENTER": FF_AUTOCENTER, + "FF_MAX_EFFECTS": FF_MAX_EFFECTS, + "FF_MAX": FF_MAX, + "EV_SYN": EV_SYN, + "EV_KEY": EV_KEY, + "EV_REL": EV_REL, + "EV_ABS": EV_ABS, + "EV_MSC": EV_MSC, + "EV_SW": EV_SW, + "EV_LED": EV_LED, + "EV_SND": EV_SND, + "EV_REP": EV_REP, + "EV_FF": EV_FF, + "EV_PWR": EV_PWR, + "EV_FF_STATUS": EV_FF_STATUS, + "EV_MAX": EV_MAX, + "SYN_REPORT": SYN_REPORT, + "SYN_CONFIG": SYN_CONFIG, + "SYN_MT_REPORT": SYN_MT_REPORT, + "SYN_DROPPED": SYN_DROPPED, + "SYN_MAX": SYN_MAX, + "KEY_RESERVED": KEY_RESERVED, + "KEY_ESC": KEY_ESC, + "KEY_1": KEY_1, + "KEY_2": KEY_2, + "KEY_3": KEY_3, + "KEY_4": KEY_4, + "KEY_5": KEY_5, + "KEY_6": KEY_6, + "KEY_7": KEY_7, + "KEY_8": KEY_8, + "KEY_9": KEY_9, + "KEY_0": KEY_0, + "KEY_MINUS": KEY_MINUS, + "KEY_EQUAL": KEY_EQUAL, + "KEY_BACKSPACE": KEY_BACKSPACE, + "KEY_TAB": KEY_TAB, + "KEY_Q": KEY_Q, + "KEY_W": KEY_W, + "KEY_E": KEY_E, + "KEY_R": KEY_R, + "KEY_T": KEY_T, + "KEY_Y": KEY_Y, + "KEY_U": KEY_U, + "KEY_I": KEY_I, + "KEY_O": KEY_O, + "KEY_P": KEY_P, + "KEY_LEFTBRACE": KEY_LEFTBRACE, + "KEY_RIGHTBRACE": KEY_RIGHTBRACE, + "KEY_ENTER": KEY_ENTER, + "KEY_LEFTCTRL": KEY_LEFTCTRL, + "KEY_A": KEY_A, + "KEY_S": KEY_S, + "KEY_D": KEY_D, + "KEY_F": KEY_F, + "KEY_G": KEY_G, + "KEY_H": KEY_H, + "KEY_J": KEY_J, + "KEY_K": KEY_K, + "KEY_L": KEY_L, + "KEY_SEMICOLON": KEY_SEMICOLON, + "KEY_APOSTROPHE": KEY_APOSTROPHE, + "KEY_GRAVE": KEY_GRAVE, + "KEY_LEFTSHIFT": KEY_LEFTSHIFT, + "KEY_BACKSLASH": KEY_BACKSLASH, + "KEY_Z": KEY_Z, + "KEY_X": KEY_X, + "KEY_C": KEY_C, + "KEY_V": KEY_V, + "KEY_B": KEY_B, + "KEY_N": KEY_N, + "KEY_M": KEY_M, + "KEY_COMMA": KEY_COMMA, + "KEY_DOT": KEY_DOT, + "KEY_SLASH": KEY_SLASH, + "KEY_RIGHTSHIFT": KEY_RIGHTSHIFT, + "KEY_KPASTERISK": KEY_KPASTERISK, + "KEY_LEFTALT": KEY_LEFTALT, + "KEY_SPACE": KEY_SPACE, + "KEY_CAPSLOCK": KEY_CAPSLOCK, + "KEY_F1": KEY_F1, + "KEY_F2": KEY_F2, + "KEY_F3": KEY_F3, + "KEY_F4": KEY_F4, + "KEY_F5": KEY_F5, + "KEY_F6": KEY_F6, + "KEY_F7": KEY_F7, + "KEY_F8": KEY_F8, + "KEY_F9": KEY_F9, + "KEY_F10": KEY_F10, + "KEY_NUMLOCK": KEY_NUMLOCK, + "KEY_SCROLLLOCK": KEY_SCROLLLOCK, + "KEY_KP7": KEY_KP7, + "KEY_KP8": KEY_KP8, + "KEY_KP9": KEY_KP9, + "KEY_KPMINUS": KEY_KPMINUS, + "KEY_KP4": KEY_KP4, + "KEY_KP5": KEY_KP5, + "KEY_KP6": KEY_KP6, + "KEY_KPPLUS": KEY_KPPLUS, + "KEY_KP1": KEY_KP1, + "KEY_KP2": KEY_KP2, + "KEY_KP3": KEY_KP3, + "KEY_KP0": KEY_KP0, + "KEY_KPDOT": KEY_KPDOT, + "KEY_ZENKAKUHANKAKU": KEY_ZENKAKUHANKAKU, + "KEY_102ND": KEY_102ND, + "KEY_F11": KEY_F11, + "KEY_F12": KEY_F12, + "KEY_RO": KEY_RO, + "KEY_KATAKANA": KEY_KATAKANA, + "KEY_HIRAGANA": KEY_HIRAGANA, + "KEY_HENKAN": KEY_HENKAN, + "KEY_KATAKANAHIRAGANA": KEY_KATAKANAHIRAGANA, + "KEY_MUHENKAN": KEY_MUHENKAN, + "KEY_KPJPCOMMA": KEY_KPJPCOMMA, + "KEY_KPENTER": KEY_KPENTER, + "KEY_RIGHTCTRL": KEY_RIGHTCTRL, + "KEY_KPSLASH": KEY_KPSLASH, + "KEY_SYSRQ": KEY_SYSRQ, + "KEY_RIGHTALT": KEY_RIGHTALT, + "KEY_LINEFEED": KEY_LINEFEED, + "KEY_HOME": KEY_HOME, + "KEY_UP": KEY_UP, + "KEY_PAGEUP": KEY_PAGEUP, + "KEY_LEFT": KEY_LEFT, + "KEY_RIGHT": KEY_RIGHT, + "KEY_END": KEY_END, + "KEY_DOWN": KEY_DOWN, + "KEY_PAGEDOWN": KEY_PAGEDOWN, + "KEY_INSERT": KEY_INSERT, + "KEY_DELETE": KEY_DELETE, + "KEY_MACRO": KEY_MACRO, + "KEY_MUTE": KEY_MUTE, + "KEY_VOLUMEDOWN": KEY_VOLUMEDOWN, + "KEY_VOLUMEUP": KEY_VOLUMEUP, + "KEY_POWER": KEY_POWER, + "KEY_KPEQUAL": KEY_KPEQUAL, + "KEY_KPPLUSMINUS": KEY_KPPLUSMINUS, + "KEY_PAUSE": KEY_PAUSE, + "KEY_SCALE": KEY_SCALE, + "KEY_KPCOMMA": KEY_KPCOMMA, + "KEY_HANGEUL": KEY_HANGEUL, + "KEY_HANGUEL": KEY_HANGUEL, + "KEY_HANJA": KEY_HANJA, + "KEY_YEN": KEY_YEN, + "KEY_LEFTMETA": KEY_LEFTMETA, + "KEY_RIGHTMETA": KEY_RIGHTMETA, + "KEY_COMPOSE": KEY_COMPOSE, + "KEY_STOP": KEY_STOP, + "KEY_AGAIN": KEY_AGAIN, + "KEY_PROPS": KEY_PROPS, + "KEY_UNDO": KEY_UNDO, + "KEY_FRONT": KEY_FRONT, + "KEY_COPY": KEY_COPY, + "KEY_OPEN": KEY_OPEN, + "KEY_PASTE": KEY_PASTE, + "KEY_FIND": KEY_FIND, + "KEY_CUT": KEY_CUT, + "KEY_HELP": KEY_HELP, + "KEY_MENU": KEY_MENU, + "KEY_CALC": KEY_CALC, + "KEY_SETUP": KEY_SETUP, + "KEY_SLEEP": KEY_SLEEP, + "KEY_WAKEUP": KEY_WAKEUP, + "KEY_FILE": KEY_FILE, + "KEY_SENDFILE": KEY_SENDFILE, + "KEY_DELETEFILE": KEY_DELETEFILE, + "KEY_XFER": KEY_XFER, + "KEY_PROG1": KEY_PROG1, + "KEY_PROG2": KEY_PROG2, + "KEY_WWW": KEY_WWW, + "KEY_MSDOS": KEY_MSDOS, + "KEY_COFFEE": KEY_COFFEE, + "KEY_SCREENLOCK": KEY_SCREENLOCK, + "KEY_ROTATE_DISPLAY": KEY_ROTATE_DISPLAY, + "KEY_DIRECTION": KEY_DIRECTION, + "KEY_CYCLEWINDOWS": KEY_CYCLEWINDOWS, + "KEY_MAIL": KEY_MAIL, + "KEY_BOOKMARKS": KEY_BOOKMARKS, + "KEY_COMPUTER": KEY_COMPUTER, + "KEY_BACK": KEY_BACK, + "KEY_FORWARD": KEY_FORWARD, + "KEY_CLOSECD": KEY_CLOSECD, + "KEY_EJECTCD": KEY_EJECTCD, + "KEY_EJECTCLOSECD": KEY_EJECTCLOSECD, + "KEY_NEXTSONG": KEY_NEXTSONG, + "KEY_PLAYPAUSE": KEY_PLAYPAUSE, + "KEY_PREVIOUSSONG": KEY_PREVIOUSSONG, + "KEY_STOPCD": KEY_STOPCD, + "KEY_RECORD": KEY_RECORD, + "KEY_REWIND": KEY_REWIND, + "KEY_PHONE": KEY_PHONE, + "KEY_ISO": KEY_ISO, + "KEY_CONFIG": KEY_CONFIG, + "KEY_HOMEPAGE": KEY_HOMEPAGE, + "KEY_REFRESH": KEY_REFRESH, + "KEY_EXIT": KEY_EXIT, + "KEY_MOVE": KEY_MOVE, + "KEY_EDIT": KEY_EDIT, + "KEY_SCROLLUP": KEY_SCROLLUP, + "KEY_SCROLLDOWN": KEY_SCROLLDOWN, + "KEY_KPLEFTPAREN": KEY_KPLEFTPAREN, + "KEY_KPRIGHTPAREN": KEY_KPRIGHTPAREN, + "KEY_NEW": KEY_NEW, + "KEY_REDO": KEY_REDO, + "KEY_F13": KEY_F13, + "KEY_F14": KEY_F14, + "KEY_F15": KEY_F15, + "KEY_F16": KEY_F16, + "KEY_F17": KEY_F17, + "KEY_F18": KEY_F18, + "KEY_F19": KEY_F19, + "KEY_F20": KEY_F20, + "KEY_F21": KEY_F21, + "KEY_F22": KEY_F22, + "KEY_F23": KEY_F23, + "KEY_F24": KEY_F24, + "KEY_PLAYCD": KEY_PLAYCD, + "KEY_PAUSECD": KEY_PAUSECD, + "KEY_PROG3": KEY_PROG3, + "KEY_PROG4": KEY_PROG4, + "KEY_DASHBOARD": KEY_DASHBOARD, + "KEY_SUSPEND": KEY_SUSPEND, + "KEY_CLOSE": KEY_CLOSE, + "KEY_PLAY": KEY_PLAY, + "KEY_FASTFORWARD": KEY_FASTFORWARD, + "KEY_BASSBOOST": KEY_BASSBOOST, + "KEY_PRINT": KEY_PRINT, + "KEY_HP": KEY_HP, + "KEY_CAMERA": KEY_CAMERA, + "KEY_SOUND": KEY_SOUND, + "KEY_QUESTION": KEY_QUESTION, + "KEY_EMAIL": KEY_EMAIL, + "KEY_CHAT": KEY_CHAT, + "KEY_SEARCH": KEY_SEARCH, + "KEY_CONNECT": KEY_CONNECT, + "KEY_FINANCE": KEY_FINANCE, + "KEY_SPORT": KEY_SPORT, + "KEY_SHOP": KEY_SHOP, + "KEY_ALTERASE": KEY_ALTERASE, + "KEY_CANCEL": KEY_CANCEL, + "KEY_BRIGHTNESSDOWN": KEY_BRIGHTNESSDOWN, + "KEY_BRIGHTNESSUP": KEY_BRIGHTNESSUP, + "KEY_MEDIA": KEY_MEDIA, + "KEY_SWITCHVIDEOMODE": KEY_SWITCHVIDEOMODE, + "KEY_KBDILLUMTOGGLE": KEY_KBDILLUMTOGGLE, + "KEY_KBDILLUMDOWN": KEY_KBDILLUMDOWN, + "KEY_KBDILLUMUP": KEY_KBDILLUMUP, + "KEY_SEND": KEY_SEND, + "KEY_REPLY": KEY_REPLY, + "KEY_FORWARDMAIL": KEY_FORWARDMAIL, + "KEY_SAVE": KEY_SAVE, + "KEY_DOCUMENTS": KEY_DOCUMENTS, + "KEY_BATTERY": KEY_BATTERY, + "KEY_BLUETOOTH": KEY_BLUETOOTH, + "KEY_WLAN": KEY_WLAN, + "KEY_UWB": KEY_UWB, + "KEY_UNKNOWN": KEY_UNKNOWN, + "KEY_VIDEO_NEXT": KEY_VIDEO_NEXT, + "KEY_VIDEO_PREV": KEY_VIDEO_PREV, + "KEY_BRIGHTNESS_CYCLE": KEY_BRIGHTNESS_CYCLE, + "KEY_BRIGHTNESS_AUTO": KEY_BRIGHTNESS_AUTO, + "KEY_BRIGHTNESS_ZERO": KEY_BRIGHTNESS_ZERO, + "KEY_DISPLAY_OFF": KEY_DISPLAY_OFF, + "KEY_WWAN": KEY_WWAN, + "KEY_WIMAX": KEY_WIMAX, + "KEY_RFKILL": KEY_RFKILL, + "KEY_MICMUTE": KEY_MICMUTE, + "BTN_MISC": BTN_MISC, + "BTN_0": BTN_0, + "BTN_1": BTN_1, + "BTN_2": BTN_2, + "BTN_3": BTN_3, + "BTN_4": BTN_4, + "BTN_5": BTN_5, + "BTN_6": BTN_6, + "BTN_7": BTN_7, + "BTN_8": BTN_8, + "BTN_9": BTN_9, + "BTN_MOUSE": BTN_MOUSE, + "BTN_LEFT": BTN_LEFT, + "BTN_RIGHT": BTN_RIGHT, + "BTN_MIDDLE": BTN_MIDDLE, + "BTN_SIDE": BTN_SIDE, + "BTN_EXTRA": BTN_EXTRA, + "BTN_FORWARD": BTN_FORWARD, + "BTN_BACK": BTN_BACK, + "BTN_TASK": BTN_TASK, + "BTN_JOYSTICK": BTN_JOYSTICK, + "BTN_TRIGGER": BTN_TRIGGER, + "BTN_THUMB": BTN_THUMB, + "BTN_THUMB2": BTN_THUMB2, + "BTN_TOP": BTN_TOP, + "BTN_TOP2": BTN_TOP2, + "BTN_PINKIE": BTN_PINKIE, + "BTN_BASE": BTN_BASE, + "BTN_BASE2": BTN_BASE2, + "BTN_BASE3": BTN_BASE3, + "BTN_BASE4": BTN_BASE4, + "BTN_BASE5": BTN_BASE5, + "BTN_BASE6": BTN_BASE6, + "BTN_DEAD": BTN_DEAD, + "BTN_GAMEPAD": BTN_GAMEPAD, + "BTN_SOUTH": BTN_SOUTH, + "BTN_A": BTN_A, + "BTN_EAST": BTN_EAST, + "BTN_B": BTN_B, + "BTN_C": BTN_C, + "BTN_NORTH": BTN_NORTH, + "BTN_X": BTN_X, + "BTN_WEST": BTN_WEST, + "BTN_Y": BTN_Y, + "BTN_Z": BTN_Z, + "BTN_TL": BTN_TL, + "BTN_TR": BTN_TR, + "BTN_TL2": BTN_TL2, + "BTN_TR2": BTN_TR2, + "BTN_SELECT": BTN_SELECT, + "BTN_START": BTN_START, + "BTN_MODE": BTN_MODE, + "BTN_THUMBL": BTN_THUMBL, + "BTN_THUMBR": BTN_THUMBR, + "BTN_DIGI": BTN_DIGI, + "BTN_TOOL_PEN": BTN_TOOL_PEN, + "BTN_TOOL_RUBBER": BTN_TOOL_RUBBER, + "BTN_TOOL_BRUSH": BTN_TOOL_BRUSH, + "BTN_TOOL_PENCIL": BTN_TOOL_PENCIL, + "BTN_TOOL_AIRBRUSH": BTN_TOOL_AIRBRUSH, + "BTN_TOOL_FINGER": BTN_TOOL_FINGER, + "BTN_TOOL_MOUSE": BTN_TOOL_MOUSE, + "BTN_TOOL_LENS": BTN_TOOL_LENS, + "BTN_TOOL_QUINTTAP": BTN_TOOL_QUINTTAP, + "BTN_TOUCH": BTN_TOUCH, + "BTN_STYLUS": BTN_STYLUS, + "BTN_STYLUS2": BTN_STYLUS2, + "BTN_TOOL_DOUBLETAP": BTN_TOOL_DOUBLETAP, + "BTN_TOOL_TRIPLETAP": BTN_TOOL_TRIPLETAP, + "BTN_TOOL_QUADTAP": BTN_TOOL_QUADTAP, + "BTN_WHEEL": BTN_WHEEL, + "BTN_GEAR_DOWN": BTN_GEAR_DOWN, + "BTN_GEAR_UP": BTN_GEAR_UP, + "KEY_OK": KEY_OK, + "KEY_SELECT": KEY_SELECT, + "KEY_GOTO": KEY_GOTO, + "KEY_CLEAR": KEY_CLEAR, + "KEY_POWER2": KEY_POWER2, + "KEY_OPTION": KEY_OPTION, + "KEY_INFO": KEY_INFO, + "KEY_TIME": KEY_TIME, + "KEY_VENDOR": KEY_VENDOR, + "KEY_ARCHIVE": KEY_ARCHIVE, + "KEY_PROGRAM": KEY_PROGRAM, + "KEY_CHANNEL": KEY_CHANNEL, + "KEY_FAVORITES": KEY_FAVORITES, + "KEY_EPG": KEY_EPG, + "KEY_PVR": KEY_PVR, + "KEY_MHP": KEY_MHP, + "KEY_LANGUAGE": KEY_LANGUAGE, + "KEY_TITLE": KEY_TITLE, + "KEY_SUBTITLE": KEY_SUBTITLE, + "KEY_ANGLE": KEY_ANGLE, + "KEY_ZOOM": KEY_ZOOM, + "KEY_MODE": KEY_MODE, + "KEY_KEYBOARD": KEY_KEYBOARD, + "KEY_SCREEN": KEY_SCREEN, + "KEY_PC": KEY_PC, + "KEY_TV": KEY_TV, + "KEY_TV2": KEY_TV2, + "KEY_VCR": KEY_VCR, + "KEY_VCR2": KEY_VCR2, + "KEY_SAT": KEY_SAT, + "KEY_SAT2": KEY_SAT2, + "KEY_CD": KEY_CD, + "KEY_TAPE": KEY_TAPE, + "KEY_RADIO": KEY_RADIO, + "KEY_TUNER": KEY_TUNER, + "KEY_PLAYER": KEY_PLAYER, + "KEY_TEXT": KEY_TEXT, + "KEY_DVD": KEY_DVD, + "KEY_AUX": KEY_AUX, + "KEY_MP3": KEY_MP3, + "KEY_AUDIO": KEY_AUDIO, + "KEY_VIDEO": KEY_VIDEO, + "KEY_DIRECTORY": KEY_DIRECTORY, + "KEY_LIST": KEY_LIST, + "KEY_MEMO": KEY_MEMO, + "KEY_CALENDAR": KEY_CALENDAR, + "KEY_RED": KEY_RED, + "KEY_GREEN": KEY_GREEN, + "KEY_YELLOW": KEY_YELLOW, + "KEY_BLUE": KEY_BLUE, + "KEY_CHANNELUP": KEY_CHANNELUP, + "KEY_CHANNELDOWN": KEY_CHANNELDOWN, + "KEY_FIRST": KEY_FIRST, + "KEY_LAST": KEY_LAST, + "KEY_AB": KEY_AB, + "KEY_NEXT": KEY_NEXT, + "KEY_RESTART": KEY_RESTART, + "KEY_SLOW": KEY_SLOW, + "KEY_SHUFFLE": KEY_SHUFFLE, + "KEY_BREAK": KEY_BREAK, + "KEY_PREVIOUS": KEY_PREVIOUS, + "KEY_DIGITS": KEY_DIGITS, + "KEY_TEEN": KEY_TEEN, + "KEY_TWEN": KEY_TWEN, + "KEY_VIDEOPHONE": KEY_VIDEOPHONE, + "KEY_GAMES": KEY_GAMES, + "KEY_ZOOMIN": KEY_ZOOMIN, + "KEY_ZOOMOUT": KEY_ZOOMOUT, + "KEY_ZOOMRESET": KEY_ZOOMRESET, + "KEY_WORDPROCESSOR": KEY_WORDPROCESSOR, + "KEY_EDITOR": KEY_EDITOR, + "KEY_SPREADSHEET": KEY_SPREADSHEET, + "KEY_GRAPHICSEDITOR": KEY_GRAPHICSEDITOR, + "KEY_PRESENTATION": KEY_PRESENTATION, + "KEY_DATABASE": KEY_DATABASE, + "KEY_NEWS": KEY_NEWS, + "KEY_VOICEMAIL": KEY_VOICEMAIL, + "KEY_ADDRESSBOOK": KEY_ADDRESSBOOK, + "KEY_MESSENGER": KEY_MESSENGER, + "KEY_DISPLAYTOGGLE": KEY_DISPLAYTOGGLE, + "KEY_BRIGHTNESS_TOGGLE": KEY_BRIGHTNESS_TOGGLE, + "KEY_SPELLCHECK": KEY_SPELLCHECK, + "KEY_LOGOFF": KEY_LOGOFF, + "KEY_DOLLAR": KEY_DOLLAR, + "KEY_EURO": KEY_EURO, + "KEY_FRAMEBACK": KEY_FRAMEBACK, + "KEY_FRAMEFORWARD": KEY_FRAMEFORWARD, + "KEY_CONTEXT_MENU": KEY_CONTEXT_MENU, + "KEY_MEDIA_REPEAT": KEY_MEDIA_REPEAT, + "KEY_10CHANNELSUP": KEY_10CHANNELSUP, + "KEY_10CHANNELSDOWN": KEY_10CHANNELSDOWN, + "KEY_IMAGES": KEY_IMAGES, + "KEY_DEL_EOL": KEY_DEL_EOL, + "KEY_DEL_EOS": KEY_DEL_EOS, + "KEY_INS_LINE": KEY_INS_LINE, + "KEY_DEL_LINE": KEY_DEL_LINE, + "KEY_FN": KEY_FN, + "KEY_FN_ESC": KEY_FN_ESC, + "KEY_FN_F1": KEY_FN_F1, + "KEY_FN_F2": KEY_FN_F2, + "KEY_FN_F3": KEY_FN_F3, + "KEY_FN_F4": KEY_FN_F4, + "KEY_FN_F5": KEY_FN_F5, + "KEY_FN_F6": KEY_FN_F6, + "KEY_FN_F7": KEY_FN_F7, + "KEY_FN_F8": KEY_FN_F8, + "KEY_FN_F9": KEY_FN_F9, + "KEY_FN_F10": KEY_FN_F10, + "KEY_FN_F11": KEY_FN_F11, + "KEY_FN_F12": KEY_FN_F12, + "KEY_FN_1": KEY_FN_1, + "KEY_FN_2": KEY_FN_2, + "KEY_FN_D": KEY_FN_D, + "KEY_FN_E": KEY_FN_E, + "KEY_FN_F": KEY_FN_F, + "KEY_FN_S": KEY_FN_S, + "KEY_FN_B": KEY_FN_B, + "KEY_BRL_DOT1": KEY_BRL_DOT1, + "KEY_BRL_DOT2": KEY_BRL_DOT2, + "KEY_BRL_DOT3": KEY_BRL_DOT3, + "KEY_BRL_DOT4": KEY_BRL_DOT4, + "KEY_BRL_DOT5": KEY_BRL_DOT5, + "KEY_BRL_DOT6": KEY_BRL_DOT6, + "KEY_BRL_DOT7": KEY_BRL_DOT7, + "KEY_BRL_DOT8": KEY_BRL_DOT8, + "KEY_BRL_DOT9": KEY_BRL_DOT9, + "KEY_BRL_DOT10": KEY_BRL_DOT10, + "KEY_NUMERIC_0": KEY_NUMERIC_0, + "KEY_NUMERIC_1": KEY_NUMERIC_1, + "KEY_NUMERIC_2": KEY_NUMERIC_2, + "KEY_NUMERIC_3": KEY_NUMERIC_3, + "KEY_NUMERIC_4": KEY_NUMERIC_4, + "KEY_NUMERIC_5": KEY_NUMERIC_5, + "KEY_NUMERIC_6": KEY_NUMERIC_6, + "KEY_NUMERIC_7": KEY_NUMERIC_7, + "KEY_NUMERIC_8": KEY_NUMERIC_8, + "KEY_NUMERIC_9": KEY_NUMERIC_9, + "KEY_NUMERIC_STAR": KEY_NUMERIC_STAR, + "KEY_NUMERIC_POUND": KEY_NUMERIC_POUND, + "KEY_NUMERIC_A": KEY_NUMERIC_A, + "KEY_NUMERIC_B": KEY_NUMERIC_B, + "KEY_NUMERIC_C": KEY_NUMERIC_C, + "KEY_NUMERIC_D": KEY_NUMERIC_D, + "KEY_CAMERA_FOCUS": KEY_CAMERA_FOCUS, + "KEY_WPS_BUTTON": KEY_WPS_BUTTON, + "KEY_TOUCHPAD_TOGGLE": KEY_TOUCHPAD_TOGGLE, + "KEY_TOUCHPAD_ON": KEY_TOUCHPAD_ON, + "KEY_TOUCHPAD_OFF": KEY_TOUCHPAD_OFF, + "KEY_CAMERA_ZOOMIN": KEY_CAMERA_ZOOMIN, + "KEY_CAMERA_ZOOMOUT": KEY_CAMERA_ZOOMOUT, + "KEY_CAMERA_UP": KEY_CAMERA_UP, + "KEY_CAMERA_DOWN": KEY_CAMERA_DOWN, + "KEY_CAMERA_LEFT": KEY_CAMERA_LEFT, + "KEY_CAMERA_RIGHT": KEY_CAMERA_RIGHT, + "KEY_ATTENDANT_ON": KEY_ATTENDANT_ON, + "KEY_ATTENDANT_OFF": KEY_ATTENDANT_OFF, + "KEY_ATTENDANT_TOGGLE": KEY_ATTENDANT_TOGGLE, + "KEY_LIGHTS_TOGGLE": KEY_LIGHTS_TOGGLE, + "BTN_DPAD_UP": BTN_DPAD_UP, + "BTN_DPAD_DOWN": BTN_DPAD_DOWN, + "BTN_DPAD_LEFT": BTN_DPAD_LEFT, + "BTN_DPAD_RIGHT": BTN_DPAD_RIGHT, + "KEY_ALS_TOGGLE": KEY_ALS_TOGGLE, + "KEY_BUTTONCONFIG": KEY_BUTTONCONFIG, + "KEY_TASKMANAGER": KEY_TASKMANAGER, + "KEY_JOURNAL": KEY_JOURNAL, + "KEY_CONTROLPANEL": KEY_CONTROLPANEL, + "KEY_APPSELECT": KEY_APPSELECT, + "KEY_SCREENSAVER": KEY_SCREENSAVER, + "KEY_VOICECOMMAND": KEY_VOICECOMMAND, + "KEY_BRIGHTNESS_MIN": KEY_BRIGHTNESS_MIN, + "KEY_BRIGHTNESS_MAX": KEY_BRIGHTNESS_MAX, + "KEY_KBDINPUTASSIST_PREV": KEY_KBDINPUTASSIST_PREV, + "KEY_KBDINPUTASSIST_NEXT": KEY_KBDINPUTASSIST_NEXT, + "KEY_KBDINPUTASSIST_PREVGROUP": KEY_KBDINPUTASSIST_PREVGROUP, + "KEY_KBDINPUTASSIST_NEXTGROUP": KEY_KBDINPUTASSIST_NEXTGROUP, + "KEY_KBDINPUTASSIST_ACCEPT": KEY_KBDINPUTASSIST_ACCEPT, + "KEY_KBDINPUTASSIST_CANCEL": KEY_KBDINPUTASSIST_CANCEL, + "KEY_RIGHT_UP": KEY_RIGHT_UP, + "KEY_RIGHT_DOWN": KEY_RIGHT_DOWN, + "KEY_LEFT_UP": KEY_LEFT_UP, + "KEY_LEFT_DOWN": KEY_LEFT_DOWN, + "KEY_ROOT_MENU": KEY_ROOT_MENU, + "KEY_MEDIA_TOP_MENU": KEY_MEDIA_TOP_MENU, + "KEY_NUMERIC_11": KEY_NUMERIC_11, + "KEY_NUMERIC_12": KEY_NUMERIC_12, + "KEY_AUDIO_DESC": KEY_AUDIO_DESC, + "KEY_3D_MODE": KEY_3D_MODE, + "KEY_NEXT_FAVORITE": KEY_NEXT_FAVORITE, + "KEY_STOP_RECORD": KEY_STOP_RECORD, + "KEY_PAUSE_RECORD": KEY_PAUSE_RECORD, + "KEY_VOD": KEY_VOD, + "KEY_UNMUTE": KEY_UNMUTE, + "KEY_FASTREVERSE": KEY_FASTREVERSE, + "KEY_SLOWREVERSE": KEY_SLOWREVERSE, + "KEY_DATA": KEY_DATA, + "BTN_TRIGGER_HAPPY": BTN_TRIGGER_HAPPY, + "BTN_TRIGGER_HAPPY1": BTN_TRIGGER_HAPPY1, + "BTN_TRIGGER_HAPPY2": BTN_TRIGGER_HAPPY2, + "BTN_TRIGGER_HAPPY3": BTN_TRIGGER_HAPPY3, + "BTN_TRIGGER_HAPPY4": BTN_TRIGGER_HAPPY4, + "BTN_TRIGGER_HAPPY5": BTN_TRIGGER_HAPPY5, + "BTN_TRIGGER_HAPPY6": BTN_TRIGGER_HAPPY6, + "BTN_TRIGGER_HAPPY7": BTN_TRIGGER_HAPPY7, + "BTN_TRIGGER_HAPPY8": BTN_TRIGGER_HAPPY8, + "BTN_TRIGGER_HAPPY9": BTN_TRIGGER_HAPPY9, + "BTN_TRIGGER_HAPPY10": BTN_TRIGGER_HAPPY10, + "BTN_TRIGGER_HAPPY11": BTN_TRIGGER_HAPPY11, + "BTN_TRIGGER_HAPPY12": BTN_TRIGGER_HAPPY12, + "BTN_TRIGGER_HAPPY13": BTN_TRIGGER_HAPPY13, + "BTN_TRIGGER_HAPPY14": BTN_TRIGGER_HAPPY14, + "BTN_TRIGGER_HAPPY15": BTN_TRIGGER_HAPPY15, + "BTN_TRIGGER_HAPPY16": BTN_TRIGGER_HAPPY16, + "BTN_TRIGGER_HAPPY17": BTN_TRIGGER_HAPPY17, + "BTN_TRIGGER_HAPPY18": BTN_TRIGGER_HAPPY18, + "BTN_TRIGGER_HAPPY19": BTN_TRIGGER_HAPPY19, + "BTN_TRIGGER_HAPPY20": BTN_TRIGGER_HAPPY20, + "BTN_TRIGGER_HAPPY21": BTN_TRIGGER_HAPPY21, + "BTN_TRIGGER_HAPPY22": BTN_TRIGGER_HAPPY22, + "BTN_TRIGGER_HAPPY23": BTN_TRIGGER_HAPPY23, + "BTN_TRIGGER_HAPPY24": BTN_TRIGGER_HAPPY24, + "BTN_TRIGGER_HAPPY25": BTN_TRIGGER_HAPPY25, + "BTN_TRIGGER_HAPPY26": BTN_TRIGGER_HAPPY26, + "BTN_TRIGGER_HAPPY27": BTN_TRIGGER_HAPPY27, + "BTN_TRIGGER_HAPPY28": BTN_TRIGGER_HAPPY28, + "BTN_TRIGGER_HAPPY29": BTN_TRIGGER_HAPPY29, + "BTN_TRIGGER_HAPPY30": BTN_TRIGGER_HAPPY30, + "BTN_TRIGGER_HAPPY31": BTN_TRIGGER_HAPPY31, + "BTN_TRIGGER_HAPPY32": BTN_TRIGGER_HAPPY32, + "BTN_TRIGGER_HAPPY33": BTN_TRIGGER_HAPPY33, + "BTN_TRIGGER_HAPPY34": BTN_TRIGGER_HAPPY34, + "BTN_TRIGGER_HAPPY35": BTN_TRIGGER_HAPPY35, + "BTN_TRIGGER_HAPPY36": BTN_TRIGGER_HAPPY36, + "BTN_TRIGGER_HAPPY37": BTN_TRIGGER_HAPPY37, + "BTN_TRIGGER_HAPPY38": BTN_TRIGGER_HAPPY38, + "BTN_TRIGGER_HAPPY39": BTN_TRIGGER_HAPPY39, + "BTN_TRIGGER_HAPPY40": BTN_TRIGGER_HAPPY40, + "KEY_MIN_INTERESTING": KEY_MIN_INTERESTING, + "KEY_MAX": KEY_MAX, + "REL_X": REL_X, + "REL_Y": REL_Y, + "REL_Z": REL_Z, + "REL_RX": REL_RX, + "REL_RY": REL_RY, + "REL_RZ": REL_RZ, + "REL_HWHEEL": REL_HWHEEL, + "REL_DIAL": REL_DIAL, + "REL_WHEEL": REL_WHEEL, + "REL_MISC": REL_MISC, + "REL_MAX": REL_MAX, + "ABS_X": ABS_X, + "ABS_Y": ABS_Y, + "ABS_Z": ABS_Z, + "ABS_RX": ABS_RX, + "ABS_RY": ABS_RY, + "ABS_RZ": ABS_RZ, + "ABS_THROTTLE": ABS_THROTTLE, + "ABS_RUDDER": ABS_RUDDER, + "ABS_WHEEL": ABS_WHEEL, + "ABS_GAS": ABS_GAS, + "ABS_BRAKE": ABS_BRAKE, + "ABS_HAT0X": ABS_HAT0X, + "ABS_HAT0Y": ABS_HAT0Y, + "ABS_HAT1X": ABS_HAT1X, + "ABS_HAT1Y": ABS_HAT1Y, + "ABS_HAT2X": ABS_HAT2X, + "ABS_HAT2Y": ABS_HAT2Y, + "ABS_HAT3X": ABS_HAT3X, + "ABS_HAT3Y": ABS_HAT3Y, + "ABS_PRESSURE": ABS_PRESSURE, + "ABS_DISTANCE": ABS_DISTANCE, + "ABS_TILT_X": ABS_TILT_X, + "ABS_TILT_Y": ABS_TILT_Y, + "ABS_TOOL_WIDTH": ABS_TOOL_WIDTH, + "ABS_VOLUME": ABS_VOLUME, + "ABS_MISC": ABS_MISC, + "ABS_MT_SLOT": ABS_MT_SLOT, + "ABS_MT_TOUCH_MAJOR": ABS_MT_TOUCH_MAJOR, + "ABS_MT_TOUCH_MINOR": ABS_MT_TOUCH_MINOR, + "ABS_MT_WIDTH_MAJOR": ABS_MT_WIDTH_MAJOR, + "ABS_MT_WIDTH_MINOR": ABS_MT_WIDTH_MINOR, + "ABS_MT_ORIENTATION": ABS_MT_ORIENTATION, + "ABS_MT_POSITION_X": ABS_MT_POSITION_X, + "ABS_MT_POSITION_Y": ABS_MT_POSITION_Y, + "ABS_MT_TOOL_TYPE": ABS_MT_TOOL_TYPE, + "ABS_MT_BLOB_ID": ABS_MT_BLOB_ID, + "ABS_MT_TRACKING_ID": ABS_MT_TRACKING_ID, + "ABS_MT_PRESSURE": ABS_MT_PRESSURE, + "ABS_MT_DISTANCE": ABS_MT_DISTANCE, + "ABS_MT_TOOL_X": ABS_MT_TOOL_X, + "ABS_MT_TOOL_Y": ABS_MT_TOOL_Y, + "ABS_MAX": ABS_MAX, + "SW_LID": SW_LID, + "SW_TABLET_MODE": SW_TABLET_MODE, + "SW_HEADPHONE_INSERT": SW_HEADPHONE_INSERT, + "SW_RFKILL_ALL": SW_RFKILL_ALL, + "SW_RADIO": SW_RADIO, + "SW_MICROPHONE_INSERT": SW_MICROPHONE_INSERT, + "SW_DOCK": SW_DOCK, + "SW_LINEOUT_INSERT": SW_LINEOUT_INSERT, + "SW_JACK_PHYSICAL_INSERT": SW_JACK_PHYSICAL_INSERT, + "SW_VIDEOOUT_INSERT": SW_VIDEOOUT_INSERT, + "SW_CAMERA_LENS_COVER": SW_CAMERA_LENS_COVER, + "SW_KEYPAD_SLIDE": SW_KEYPAD_SLIDE, + "SW_FRONT_PROXIMITY": SW_FRONT_PROXIMITY, + "SW_ROTATE_LOCK": SW_ROTATE_LOCK, + "SW_LINEIN_INSERT": SW_LINEIN_INSERT, + "SW_MUTE_DEVICE": SW_MUTE_DEVICE, + "SW_PEN_INSERTED": SW_PEN_INSERTED, + "SW_MAX": SW_MAX, + "MSC_SERIAL": MSC_SERIAL, + "MSC_PULSELED": MSC_PULSELED, + "MSC_GESTURE": MSC_GESTURE, + "MSC_RAW": MSC_RAW, + "MSC_SCAN": MSC_SCAN, + "MSC_TIMESTAMP": MSC_TIMESTAMP, + "MSC_MAX": MSC_MAX, + "LED_NUML": LED_NUML, + "LED_CAPSL": LED_CAPSL, + "LED_SCROLLL": LED_SCROLLL, + "LED_COMPOSE": LED_COMPOSE, + "LED_KANA": LED_KANA, + "LED_SLEEP": LED_SLEEP, + "LED_SUSPEND": LED_SUSPEND, + "LED_MUTE": LED_MUTE, + "LED_MISC": LED_MISC, + "LED_MAIL": LED_MAIL, + "LED_CHARGING": LED_CHARGING, + "LED_MAX": LED_MAX, + "REP_DELAY": REP_DELAY, + "REP_PERIOD": REP_PERIOD, + "REP_MAX": REP_MAX, + "SND_CLICK": SND_CLICK, + "SND_BELL": SND_BELL, + "SND_TONE": SND_TONE, + "SND_MAX": SND_MAX, +} + +var KEY = map[int]string{} +var ABS = map[int]string{} +var REL = map[int]string{} +var SW = map[int]string{} +var MSC = map[int]string{} +var LED = map[int]string{} +var BTN = map[int]string{} +var REP = map[int]string{} +var SND = map[int]string{} +var ID = map[int]string{} +var EV = map[int]string{} +var BUS = map[int]string{} +var SYN = map[int]string{} +var FF = map[int]string{} + +var ByEventType = map[int]map[int]string{ + EV_KEY: KEY, + EV_ABS: ABS, + EV_REL: REL, + EV_SW: SW, + EV_MSC: MSC, + EV_LED: LED, + EV_REP: REP, + EV_SND: SND, + EV_SYN: SYN, + EV_FF: FF, +} + +func init() { + for code, value := range ecodes { + switch { + case strings.HasPrefix(code, "KEY"): + KEY[value] = code + case strings.HasPrefix(code, "ABS"): + ABS[value] = code + case strings.HasPrefix(code, "REL"): + REL[value] = code + case strings.HasPrefix(code, "SW"): + SW[value] = code + case strings.HasPrefix(code, "MSC"): + MSC[value] = code + case strings.HasPrefix(code, "LED"): + LED[value] = code + case strings.HasPrefix(code, "BTN"): + BTN[value] = code + case strings.HasPrefix(code, "SND"): + SND[value] = code + case strings.HasPrefix(code, "ID"): + ID[value] = code + case strings.HasPrefix(code, "EV"): + EV[value] = code + case strings.HasPrefix(code, "BUS"): + BUS[value] = code + case strings.HasPrefix(code, "SYN"): + SYN[value] = code + case strings.HasPrefix(code, "FF"): + FF[value] = code + } + } +} diff --git a/vendor/github.com/gvalkov/golang-evdev/ecodes.go.template b/vendor/github.com/gvalkov/golang-evdev/ecodes.go.template new file mode 100644 index 0000000..a73e3f4 --- /dev/null +++ b/vendor/github.com/gvalkov/golang-evdev/ecodes.go.template @@ -0,0 +1,88 @@ +// -*- mode: go; -*- + +// Integer constants defined in linux/input.h and linux/input-event-codes.h can be accessed +// directly as constants or through the provided reverse and forward mappings: + +// +// evdev.KEY_A // 30 +// evdev.ecodes["KEY_A"] // 30 +// evdev.KEY[30] // "KEY_A" +// evdev.REL[0] // "REL_X" +// evdev.EV[evdev.EV_KEY] // "EV_KEY" +// evdev.ByEventType[EV_REL][0] // "REL_X" +// +// Generated on: ${UNAME} + +package evdev + +import "strings" + +const ( +${CODES} +) + +var ecodes = map[string] int { +${CODEMAP} +} + + +var KEY = map[int]string {} +var ABS = map[int]string {} +var REL = map[int]string {} +var SW = map[int]string {} +var MSC = map[int]string {} +var LED = map[int]string {} +var BTN = map[int]string {} +var REP = map[int]string {} +var SND = map[int]string {} +var ID = map[int]string {} +var EV = map[int]string {} +var BUS = map[int]string {} +var SYN = map[int]string {} +var FF = map[int]string {} + +var ByEventType = map[int] map[int]string { + EV_KEY: KEY, + EV_ABS: ABS, + EV_REL: REL, + EV_SW: SW, + EV_MSC: MSC, + EV_LED: LED, + EV_REP: REP, + EV_SND: SND, + EV_SYN: SYN, + EV_FF: FF, +} + +func init() { + for code, value := range ecodes { + switch { + case strings.HasPrefix(code, "KEY"): + KEY[value] = code + case strings.HasPrefix(code, "ABS"): + ABS[value] = code + case strings.HasPrefix(code, "REL"): + REL[value] = code + case strings.HasPrefix(code, "SW"): + SW[value] = code + case strings.HasPrefix(code, "MSC"): + MSC[value] = code + case strings.HasPrefix(code, "LED"): + LED[value] = code + case strings.HasPrefix(code, "BTN"): + BTN[value] = code + case strings.HasPrefix(code, "SND"): + SND[value] = code + case strings.HasPrefix(code, "ID"): + ID[value] = code + case strings.HasPrefix(code, "EV"): + EV[value] = code + case strings.HasPrefix(code, "BUS"): + BUS[value] = code + case strings.HasPrefix(code, "SYN"): + SYN[value] = code + case strings.HasPrefix(code, "FF"): + FF[value] = code + } + } +} diff --git a/vendor/github.com/gvalkov/golang-evdev/events.go b/vendor/github.com/gvalkov/golang-evdev/events.go new file mode 100644 index 0000000..f4299b6 --- /dev/null +++ b/vendor/github.com/gvalkov/golang-evdev/events.go @@ -0,0 +1,109 @@ +package evdev + +import ( + "fmt" + "syscall" + "unsafe" +) + +type InputEvent struct { + Time syscall.Timeval // time in seconds since epoch at which event occurred + Type uint16 // event type - one of ecodes.EV_* + Code uint16 // event code related to the event type + Value int32 // event value related to the event type +} + +// Get a useful description for an input event. Example: +// event at 1347905437.435795, code 01, type 02, val 02 +func (ev *InputEvent) String() string { + return fmt.Sprintf("event at %d.%d, code %02d, type %02d, val %02d", + ev.Time.Sec, ev.Time.Usec, ev.Code, ev.Type, ev.Value) +} + +var eventsize = int(unsafe.Sizeof(InputEvent{})) + +type KeyEventState uint8 + +const ( + KeyUp KeyEventState = 0x0 + KeyDown KeyEventState = 0x1 + KeyHold KeyEventState = 0x2 +) + +// KeyEvents are used to describe state changes of keyboards, buttons, +// or other key-like devices. +type KeyEvent struct { + Event *InputEvent + Scancode uint16 + Keycode uint16 + State KeyEventState +} + +func (kev *KeyEvent) New(ev *InputEvent) { + kev.Event = ev + kev.Keycode = 0 // :todo + kev.Scancode = ev.Code + + switch ev.Value { + case 0: + kev.State = KeyUp + case 2: + kev.State = KeyHold + case 1: + kev.State = KeyDown + } +} + +func NewKeyEvent(ev *InputEvent) *KeyEvent { + kev := &KeyEvent{} + kev.New(ev) + return kev +} + +func (ev *KeyEvent) String() string { + state := "unknown" + + switch ev.State { + case KeyUp: + state = "up" + case KeyHold: + state = "hold" + case KeyDown: + state = "down" + } + + return fmt.Sprintf("key event at %d.%d, %d (%d), (%s)", + ev.Event.Time.Sec, ev.Event.Time.Usec, + ev.Scancode, ev.Event.Code, state) +} + +// RelEvents are used to describe relative axis value changes, +// e.g. moving the mouse 5 units to the left. +type RelEvent struct { + Event *InputEvent +} + +func (rev *RelEvent) New(ev *InputEvent) { + rev.Event = ev +} + +func NewRelEvent(ev *InputEvent) *RelEvent { + rev := &RelEvent{} + rev.New(ev) + return rev +} + +func (ev *RelEvent) String() string { + return fmt.Sprintf("relative axis event at %d.%d, %s", + ev.Event.Time.Sec, ev.Event.Time.Usec, + REL[int(ev.Event.Code)]) +} + +// TODO: Make this work + +var EventFactory map[uint16]interface{} = make(map[uint16]interface{}) + +func init() { + EventFactory[uint16(EV_KEY)] = NewKeyEvent + EventFactory[uint16(EV_REL)] = NewRelEvent +} diff --git a/vendor/github.com/pmezard/go-difflib/LICENSE b/vendor/github.com/pmezard/go-difflib/LICENSE new file mode 100644 index 0000000..c67dad6 --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013, Patrick Mezard +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. + The names of its contributors may not 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 +HOLDER 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. diff --git a/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go new file mode 100644 index 0000000..64cc40f --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go @@ -0,0 +1,758 @@ +// Package difflib is a partial port of Python difflib module. +// +// It provides tools to compare sequences of strings and generate textual diffs. +// +// The following class and functions have been ported: +// +// - SequenceMatcher +// +// - unified_diff +// +// - context_diff +// +// Getting unified diffs was the main goal of the port. Keep in mind this code +// is mostly suitable to output text differences in a human friendly way, there +// are no guarantees generated diffs are consumable by patch(1). +package difflib + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strings" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func calculateRatio(matches, length int) float64 { + if length > 0 { + return 2.0 * float64(matches) / float64(length) + } + return 1.0 +} + +type Match struct { + A int + B int + Size int +} + +type OpCode struct { + Tag byte + I1 int + I2 int + J1 int + J2 int +} + +// SequenceMatcher compares sequence of strings. The basic +// algorithm predates, and is a little fancier than, an algorithm +// published in the late 1980's by Ratcliff and Obershelp under the +// hyperbolic name "gestalt pattern matching". The basic idea is to find +// the longest contiguous matching subsequence that contains no "junk" +// elements (R-O doesn't address junk). The same idea is then applied +// recursively to the pieces of the sequences to the left and to the right +// of the matching subsequence. This does not yield minimal edit +// sequences, but does tend to yield matches that "look right" to people. +// +// SequenceMatcher tries to compute a "human-friendly diff" between two +// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the +// longest *contiguous* & junk-free matching subsequence. That's what +// catches peoples' eyes. The Windows(tm) windiff has another interesting +// notion, pairing up elements that appear uniquely in each sequence. +// That, and the method here, appear to yield more intuitive difference +// reports than does diff. This method appears to be the least vulnerable +// to synching up on blocks of "junk lines", though (like blank lines in +// ordinary text files, or maybe "

" lines in HTML files). That may be +// because this is the only method of the 3 that has a *concept* of +// "junk" . +// +// Timing: Basic R-O is cubic time worst case and quadratic time expected +// case. SequenceMatcher is quadratic time for the worst case and has +// expected-case behavior dependent in a complicated way on how many +// elements the sequences have in common; best case time is linear. +type SequenceMatcher struct { + a []string + b []string + b2j map[string][]int + IsJunk func(string) bool + autoJunk bool + bJunk map[string]struct{} + matchingBlocks []Match + fullBCount map[string]int + bPopular map[string]struct{} + opCodes []OpCode +} + +func NewMatcher(a, b []string) *SequenceMatcher { + m := SequenceMatcher{autoJunk: true} + m.SetSeqs(a, b) + return &m +} + +func NewMatcherWithJunk(a, b []string, autoJunk bool, + isJunk func(string) bool) *SequenceMatcher { + + m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} + m.SetSeqs(a, b) + return &m +} + +// Set two sequences to be compared. +func (m *SequenceMatcher) SetSeqs(a, b []string) { + m.SetSeq1(a) + m.SetSeq2(b) +} + +// Set the first sequence to be compared. The second sequence to be compared is +// not changed. +// +// SequenceMatcher computes and caches detailed information about the second +// sequence, so if you want to compare one sequence S against many sequences, +// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other +// sequences. +// +// See also SetSeqs() and SetSeq2(). +func (m *SequenceMatcher) SetSeq1(a []string) { + if &a == &m.a { + return + } + m.a = a + m.matchingBlocks = nil + m.opCodes = nil +} + +// Set the second sequence to be compared. The first sequence to be compared is +// not changed. +func (m *SequenceMatcher) SetSeq2(b []string) { + if &b == &m.b { + return + } + m.b = b + m.matchingBlocks = nil + m.opCodes = nil + m.fullBCount = nil + m.chainB() +} + +func (m *SequenceMatcher) chainB() { + // Populate line -> index mapping + b2j := map[string][]int{} + for i, s := range m.b { + indices := b2j[s] + indices = append(indices, i) + b2j[s] = indices + } + + // Purge junk elements + m.bJunk = map[string]struct{}{} + if m.IsJunk != nil { + junk := m.bJunk + for s, _ := range b2j { + if m.IsJunk(s) { + junk[s] = struct{}{} + } + } + for s, _ := range junk { + delete(b2j, s) + } + } + + // Purge remaining popular elements + popular := map[string]struct{}{} + n := len(m.b) + if m.autoJunk && n >= 200 { + ntest := n/100 + 1 + for s, indices := range b2j { + if len(indices) > ntest { + popular[s] = struct{}{} + } + } + for s, _ := range popular { + delete(b2j, s) + } + } + m.bPopular = popular + m.b2j = b2j +} + +func (m *SequenceMatcher) isBJunk(s string) bool { + _, ok := m.bJunk[s] + return ok +} + +// Find longest matching block in a[alo:ahi] and b[blo:bhi]. +// +// If IsJunk is not defined: +// +// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where +// alo <= i <= i+k <= ahi +// blo <= j <= j+k <= bhi +// and for all (i',j',k') meeting those conditions, +// k >= k' +// i <= i' +// and if i == i', j <= j' +// +// In other words, of all maximal matching blocks, return one that +// starts earliest in a, and of all those maximal matching blocks that +// start earliest in a, return the one that starts earliest in b. +// +// If IsJunk is defined, first the longest matching block is +// determined as above, but with the additional restriction that no +// junk element appears in the block. Then that block is extended as +// far as possible by matching (only) junk elements on both sides. So +// the resulting block never matches on junk except as identical junk +// happens to be adjacent to an "interesting" match. +// +// If no blocks match, return (alo, blo, 0). +func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { + // CAUTION: stripping common prefix or suffix would be incorrect. + // E.g., + // ab + // acab + // Longest matching block is "ab", but if common prefix is + // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so + // strip, so ends up claiming that ab is changed to acab by + // inserting "ca" in the middle. That's minimal but unintuitive: + // "it's obvious" that someone inserted "ac" at the front. + // Windiff ends up at the same place as diff, but by pairing up + // the unique 'b's and then matching the first two 'a's. + besti, bestj, bestsize := alo, blo, 0 + + // find longest junk-free match + // during an iteration of the loop, j2len[j] = length of longest + // junk-free match ending with a[i-1] and b[j] + j2len := map[int]int{} + for i := alo; i != ahi; i++ { + // look at all instances of a[i] in b; note that because + // b2j has no junk keys, the loop is skipped if a[i] is junk + newj2len := map[int]int{} + for _, j := range m.b2j[m.a[i]] { + // a[i] matches b[j] + if j < blo { + continue + } + if j >= bhi { + break + } + k := j2len[j-1] + 1 + newj2len[j] = k + if k > bestsize { + besti, bestj, bestsize = i-k+1, j-k+1, k + } + } + j2len = newj2len + } + + // Extend the best by non-junk elements on each end. In particular, + // "popular" non-junk elements aren't in b2j, which greatly speeds + // the inner loop above, but also means "the best" match so far + // doesn't contain any junk *or* popular non-junk elements. + for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + !m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + // Now that we have a wholly interesting match (albeit possibly + // empty!), we may as well suck up the matching junk on each + // side of it too. Can't think of a good reason not to, and it + // saves post-processing the (possibly considerable) expense of + // figuring out what to do with it. In the case of an empty + // interesting match, this is clearly the right thing to do, + // because no other kind of match is possible in the regions. + for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + return Match{A: besti, B: bestj, Size: bestsize} +} + +// Return list of triples describing matching subsequences. +// +// Each triple is of the form (i, j, n), and means that +// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in +// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are +// adjacent triples in the list, and the second is not the last triple in the +// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe +// adjacent equal blocks. +// +// The last triple is a dummy, (len(a), len(b), 0), and is the only +// triple with n==0. +func (m *SequenceMatcher) GetMatchingBlocks() []Match { + if m.matchingBlocks != nil { + return m.matchingBlocks + } + + var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match + matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { + match := m.findLongestMatch(alo, ahi, blo, bhi) + i, j, k := match.A, match.B, match.Size + if match.Size > 0 { + if alo < i && blo < j { + matched = matchBlocks(alo, i, blo, j, matched) + } + matched = append(matched, match) + if i+k < ahi && j+k < bhi { + matched = matchBlocks(i+k, ahi, j+k, bhi, matched) + } + } + return matched + } + matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) + + // It's possible that we have adjacent equal blocks in the + // matching_blocks list now. + nonAdjacent := []Match{} + i1, j1, k1 := 0, 0, 0 + for _, b := range matched { + // Is this block adjacent to i1, j1, k1? + i2, j2, k2 := b.A, b.B, b.Size + if i1+k1 == i2 && j1+k1 == j2 { + // Yes, so collapse them -- this just increases the length of + // the first block by the length of the second, and the first + // block so lengthened remains the block to compare against. + k1 += k2 + } else { + // Not adjacent. Remember the first block (k1==0 means it's + // the dummy we started with), and make the second block the + // new block to compare against. + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + i1, j1, k1 = i2, j2, k2 + } + } + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + + nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) + m.matchingBlocks = nonAdjacent + return m.matchingBlocks +} + +// Return list of 5-tuples describing how to turn a into b. +// +// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple +// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the +// tuple preceding it, and likewise for j1 == the previous j2. +// +// The tags are characters, with these meanings: +// +// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] +// +// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. +// +// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. +// +// 'e' (equal): a[i1:i2] == b[j1:j2] +func (m *SequenceMatcher) GetOpCodes() []OpCode { + if m.opCodes != nil { + return m.opCodes + } + i, j := 0, 0 + matching := m.GetMatchingBlocks() + opCodes := make([]OpCode, 0, len(matching)) + for _, m := range matching { + // invariant: we've pumped out correct diffs to change + // a[:i] into b[:j], and the next matching block is + // a[ai:ai+size] == b[bj:bj+size]. So we need to pump + // out a diff to change a[i:ai] into b[j:bj], pump out + // the matching block, and move (i,j) beyond the match + ai, bj, size := m.A, m.B, m.Size + tag := byte(0) + if i < ai && j < bj { + tag = 'r' + } else if i < ai { + tag = 'd' + } else if j < bj { + tag = 'i' + } + if tag > 0 { + opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) + } + i, j = ai+size, bj+size + // the list of matching blocks is terminated by a + // sentinel with size 0 + if size > 0 { + opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) + } + } + m.opCodes = opCodes + return m.opCodes +} + +// Isolate change clusters by eliminating ranges with no changes. +// +// Return a generator of groups with up to n lines of context. +// Each group is in the same format as returned by GetOpCodes(). +func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { + if n < 0 { + n = 3 + } + codes := m.GetOpCodes() + if len(codes) == 0 { + codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} + } + // Fixup leading and trailing groups if they show no changes. + if codes[0].Tag == 'e' { + c := codes[0] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} + } + if codes[len(codes)-1].Tag == 'e' { + c := codes[len(codes)-1] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} + } + nn := n + n + groups := [][]OpCode{} + group := []OpCode{} + for _, c := range codes { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + // End the current group and start a new one whenever + // there is a large range with no changes. + if c.Tag == 'e' && i2-i1 > nn { + group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), + j1, min(j2, j1+n)}) + groups = append(groups, group) + group = []OpCode{} + i1, j1 = max(i1, i2-n), max(j1, j2-n) + } + group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) + } + if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { + groups = append(groups, group) + } + return groups +} + +// Return a measure of the sequences' similarity (float in [0,1]). +// +// Where T is the total number of elements in both sequences, and +// M is the number of matches, this is 2.0*M / T. +// Note that this is 1 if the sequences are identical, and 0 if +// they have nothing in common. +// +// .Ratio() is expensive to compute if you haven't already computed +// .GetMatchingBlocks() or .GetOpCodes(), in which case you may +// want to try .QuickRatio() or .RealQuickRation() first to get an +// upper bound. +func (m *SequenceMatcher) Ratio() float64 { + matches := 0 + for _, m := range m.GetMatchingBlocks() { + matches += m.Size + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() relatively quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute. +func (m *SequenceMatcher) QuickRatio() float64 { + // viewing a and b as multisets, set matches to the cardinality + // of their intersection; this counts the number of matches + // without regard to order, so is clearly an upper bound + if m.fullBCount == nil { + m.fullBCount = map[string]int{} + for _, s := range m.b { + m.fullBCount[s] = m.fullBCount[s] + 1 + } + } + + // avail[x] is the number of times x appears in 'b' less the + // number of times we've seen it in 'a' so far ... kinda + avail := map[string]int{} + matches := 0 + for _, s := range m.a { + n, ok := avail[s] + if !ok { + n = m.fullBCount[s] + } + avail[s] = n - 1 + if n > 0 { + matches += 1 + } + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() very quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute than either .Ratio() or .QuickRatio(). +func (m *SequenceMatcher) RealQuickRatio() float64 { + la, lb := len(m.a), len(m.b) + return calculateRatio(min(la, lb), la+lb) +} + +// Convert range to the "ed" format +func formatRangeUnified(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 1 { + return fmt.Sprintf("%d", beginning) + } + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + return fmt.Sprintf("%d,%d", beginning, length) +} + +// Unified diff parameters +type UnifiedDiff struct { + A []string // First sequence lines + FromFile string // First file name + FromDate string // First file time + B []string // Second sequence lines + ToFile string // Second file name + ToDate string // Second file time + Eol string // Headers end of line, defaults to LF + Context int // Number of context lines +} + +// Compare two sequences of lines; generate the delta as a unified diff. +// +// Unified diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by 'n' which +// defaults to three. +// +// By default, the diff control lines (those with ---, +++, or @@) are +// created with a trailing newline. This is helpful so that inputs +// created from file.readlines() result in diffs that are suitable for +// file.writelines() since both the inputs and outputs have trailing +// newlines. +// +// For inputs that do not have trailing newlines, set the lineterm +// argument to "" so that the output will be uniformly newline free. +// +// The unidiff format normally has a header for filenames and modification +// times. Any or all of these may be specified using strings for +// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. +// The modification times are normally expressed in the ISO 8601 format. +func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + w := func(format string, args ...interface{}) error { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + return err + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + err := w("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) + if err != nil { + return err + } + err = w("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) + if err != nil { + return err + } + } + first, last := g[0], g[len(g)-1] + range1 := formatRangeUnified(first.I1, last.I2) + range2 := formatRangeUnified(first.J1, last.J2) + if err := w("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { + return err + } + for _, c := range g { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + if c.Tag == 'e' { + for _, line := range diff.A[i1:i2] { + if err := w(" " + line); err != nil { + return err + } + } + continue + } + if c.Tag == 'r' || c.Tag == 'd' { + for _, line := range diff.A[i1:i2] { + if err := w("-" + line); err != nil { + return err + } + } + } + if c.Tag == 'r' || c.Tag == 'i' { + for _, line := range diff.B[j1:j2] { + if err := w("+" + line); err != nil { + return err + } + } + } + } + } + return nil +} + +// Like WriteUnifiedDiff but returns the diff a string. +func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteUnifiedDiff(w, diff) + return string(w.Bytes()), err +} + +// Convert range to the "ed" format. +func formatRangeContext(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + if length <= 1 { + return fmt.Sprintf("%d", beginning) + } + return fmt.Sprintf("%d,%d", beginning, beginning+length-1) +} + +type ContextDiff UnifiedDiff + +// Compare two sequences of lines; generate the delta as a context diff. +// +// Context diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by diff.Context +// which defaults to three. +// +// By default, the diff control lines (those with *** or ---) are +// created with a trailing newline. +// +// For inputs that do not have trailing newlines, set the diff.Eol +// argument to "" so that the output will be uniformly newline free. +// +// The context diff format normally has a header for filenames and +// modification times. Any or all of these may be specified using +// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. +// The modification times are normally expressed in the ISO 8601 format. +// If not specified, the strings default to blanks. +func WriteContextDiff(writer io.Writer, diff ContextDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + var diffErr error + w := func(format string, args ...interface{}) { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + if diffErr == nil && err != nil { + diffErr = err + } + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + prefix := map[byte]string{ + 'i': "+ ", + 'd': "- ", + 'r': "! ", + 'e': " ", + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + w("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) + w("--- %s%s%s", diff.ToFile, toDate, diff.Eol) + } + + first, last := g[0], g[len(g)-1] + w("***************" + diff.Eol) + + range1 := formatRangeContext(first.I1, last.I2) + w("*** %s ****%s", range1, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'd' { + for _, cc := range g { + if cc.Tag == 'i' { + continue + } + for _, line := range diff.A[cc.I1:cc.I2] { + w(prefix[cc.Tag] + line) + } + } + break + } + } + + range2 := formatRangeContext(first.J1, last.J2) + w("--- %s ----%s", range2, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'i' { + for _, cc := range g { + if cc.Tag == 'd' { + continue + } + for _, line := range diff.B[cc.J1:cc.J2] { + w(prefix[cc.Tag] + line) + } + } + break + } + } + } + return diffErr +} + +// Like WriteContextDiff but returns the diff a string. +func GetContextDiffString(diff ContextDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteContextDiff(w, diff) + return string(w.Bytes()), err +} + +// Split a string on "\n" while preserving them. The output can be used +// as input for UnifiedDiff and ContextDiff structures. +func SplitLines(s string) []string { + lines := strings.SplitAfter(s, "\n") + lines[len(lines)-1] += "\n" + return lines +} diff --git a/vendor/github.com/stretchr/testify/LICENSE b/vendor/github.com/stretchr/testify/LICENSE new file mode 100644 index 0000000..473b670 --- /dev/null +++ b/vendor/github.com/stretchr/testify/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell + +Please consider promoting this project if you find it useful. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/stretchr/testify/assert/assert.test b/vendor/github.com/stretchr/testify/assert/assert.test new file mode 100755 index 0000000..81b556f Binary files /dev/null and b/vendor/github.com/stretchr/testify/assert/assert.test differ diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go new file mode 100644 index 0000000..aa4311f --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -0,0 +1,352 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package assert + +import ( + http "net/http" + url "net/url" + time "time" +) + +// Condition uses a Comparison to assert a complex condition. +func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { + return Condition(a.t, comp, msgAndArgs...) +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Contains("Hello World", "World", "But 'Hello World' does contain 'World'") +// a.Contains(["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'") +// a.Contains({"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + return Contains(a.t, s, contains, msgAndArgs...) +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Empty(obj) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { + return Empty(a.t, object, msgAndArgs...) +} + +// Equal asserts that two objects are equal. +// +// a.Equal(123, 123, "123 and 123 should be equal") +// +// Returns whether the assertion was successful (true) or not (false). +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + return Equal(a.t, expected, actual, msgAndArgs...) +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualError(err, expectedErrorString, "An error was expected") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { + return EqualError(a.t, theError, errString, msgAndArgs...) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValues(uint32(123), int32(123), "123 and 123 should be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + return EqualValues(a.t, expected, actual, msgAndArgs...) +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Error(err, "An error was expected") { +// assert.Equal(t, err, expectedError) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { + return Error(a.t, err, msgAndArgs...) +} + +// Exactly asserts that two objects are equal is value and type. +// +// a.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + return Exactly(a.t, expected, actual, msgAndArgs...) +} + +// Fail reports a failure through +func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { + return Fail(a.t, failureMessage, msgAndArgs...) +} + +// FailNow fails test +func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { + return FailNow(a.t, failureMessage, msgAndArgs...) +} + +// False asserts that the specified value is false. +// +// a.False(myBool, "myBool should be false") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { + return False(a.t, value, msgAndArgs...) +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool { + return HTTPBodyContains(a.t, handler, method, url, values, str) +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool { + return HTTPBodyNotContains(a.t, handler, method, url, values, str) +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values) bool { + return HTTPError(a.t, handler, method, url, values) +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values) bool { + return HTTPRedirect(a.t, handler, method, url, values) +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values) bool { + return HTTPSuccess(a.t, handler, method, url, values) +} + +// Implements asserts that an object is implemented by the specified interface. +// +// a.Implements((*MyInterface)(nil), new(MyObject), "MyObject") +func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + return Implements(a.t, interfaceObject, object, msgAndArgs...) +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// a.InDelta(math.Pi, (22 / 7.0), 0.01) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + return InDelta(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// IsType asserts that the specified objects are of the same type. +func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + return IsType(a.t, expectedType, object, msgAndArgs...) +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { + return JSONEq(a.t, expected, actual, msgAndArgs...) +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// a.Len(mySlice, 3, "The size of slice is not 3") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { + return Len(a.t, object, length, msgAndArgs...) +} + +// Nil asserts that the specified object is nil. +// +// a.Nil(err, "err should be nothing") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { + return Nil(a.t, object, msgAndArgs...) +} + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoError(err) { +// assert.Equal(t, actualObj, expectedObj) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { + return NoError(a.t, err, msgAndArgs...) +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'") +// a.NotContains(["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'") +// a.NotContains({"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + return NotContains(a.t, s, contains, msgAndArgs...) +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmpty(obj) { +// assert.Equal(t, "two", obj[1]) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { + return NotEmpty(a.t, object, msgAndArgs...) +} + +// NotEqual asserts that the specified values are NOT equal. +// +// a.NotEqual(obj1, obj2, "two objects shouldn't be equal") +// +// Returns whether the assertion was successful (true) or not (false). +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + return NotEqual(a.t, expected, actual, msgAndArgs...) +} + +// NotNil asserts that the specified object is not nil. +// +// a.NotNil(err, "err should be something") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { + return NotNil(a.t, object, msgAndArgs...) +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanics(func(){ +// RemainCalm() +// }, "Calling RemainCalm() should NOT panic") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + return NotPanics(a.t, f, msgAndArgs...) +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") +// a.NotRegexp("^start", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + return NotRegexp(a.t, rx, str, msgAndArgs...) +} + +// NotZero asserts that i is not the zero value for its type and returns the truth. +func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { + return NotZero(a.t, i, msgAndArgs...) +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panics(func(){ +// GoCrazy() +// }, "Calling GoCrazy() should panic") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + return Panics(a.t, f, msgAndArgs...) +} + +// Regexp asserts that a specified regexp matches a string. +// +// a.Regexp(regexp.MustCompile("start"), "it's starting") +// a.Regexp("start...$", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + return Regexp(a.t, rx, str, msgAndArgs...) +} + +// True asserts that the specified value is true. +// +// a.True(myBool, "myBool should be true") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { + return True(a.t, value, msgAndArgs...) +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// a.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) +} + +// Zero asserts that i is the zero value for its type and returns the truth. +func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { + return Zero(a.t, i, msgAndArgs...) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl new file mode 100644 index 0000000..99f9acf --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl @@ -0,0 +1,4 @@ +{{.CommentWithoutT "a"}} +func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { + return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go new file mode 100644 index 0000000..d1552e5 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -0,0 +1,1069 @@ +package assert + +import ( + "bufio" + "bytes" + "encoding/json" + "fmt" + "math" + "reflect" + "regexp" + "runtime" + "strings" + "time" + "unicode" + "unicode/utf8" + + "github.com/davecgh/go-spew/spew" + "github.com/pmezard/go-difflib/difflib" +) + +// TestingT is an interface wrapper around *testing.T +type TestingT interface { + Errorf(format string, args ...interface{}) +} + +// Comparison a custom function that returns true on success and false on failure +type Comparison func() (success bool) + +/* + Helper functions +*/ + +// ObjectsAreEqual determines if two objects are considered equal. +// +// This function does no assertion of any kind. +func ObjectsAreEqual(expected, actual interface{}) bool { + + if expected == nil || actual == nil { + return expected == actual + } + + return reflect.DeepEqual(expected, actual) + +} + +// ObjectsAreEqualValues gets whether two objects are equal, or if their +// values are equal. +func ObjectsAreEqualValues(expected, actual interface{}) bool { + if ObjectsAreEqual(expected, actual) { + return true + } + + actualType := reflect.TypeOf(actual) + if actualType == nil { + return false + } + expectedValue := reflect.ValueOf(expected) + if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { + // Attempt comparison after type conversion + return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) + } + + return false +} + +/* CallerInfo is necessary because the assert functions use the testing object +internally, causing it to print the file:line of the assert method, rather than where +the problem actually occurred in calling code.*/ + +// CallerInfo returns an array of strings containing the file and line number +// of each stack frame leading from the current test to the assert call that +// failed. +func CallerInfo() []string { + + pc := uintptr(0) + file := "" + line := 0 + ok := false + name := "" + + callers := []string{} + for i := 0; ; i++ { + pc, file, line, ok = runtime.Caller(i) + if !ok { + // The breaks below failed to terminate the loop, and we ran off the + // end of the call stack. + break + } + + // This is a huge edge case, but it will panic if this is the case, see #180 + if file == "" { + break + } + + f := runtime.FuncForPC(pc) + if f == nil { + break + } + name = f.Name() + + // testing.tRunner is the standard library function that calls + // tests. Subtests are called directly by tRunner, without going through + // the Test/Benchmark/Example function that contains the t.Run calls, so + // with subtests we should break when we hit tRunner, without adding it + // to the list of callers. + if name == "testing.tRunner" { + break + } + + parts := strings.Split(file, "/") + dir := parts[len(parts)-2] + file = parts[len(parts)-1] + if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { + callers = append(callers, fmt.Sprintf("%s:%d", file, line)) + } + + // Drop the package + segments := strings.Split(name, ".") + name = segments[len(segments)-1] + if isTest(name, "Test") || + isTest(name, "Benchmark") || + isTest(name, "Example") { + break + } + } + + return callers +} + +// Stolen from the `go test` tool. +// isTest tells whether name looks like a test (or benchmark, according to prefix). +// It is a Test (say) if there is a character after Test that is not a lower-case letter. +// We don't want TesticularCancer. +func isTest(name, prefix string) bool { + if !strings.HasPrefix(name, prefix) { + return false + } + if len(name) == len(prefix) { // "Test" is ok + return true + } + rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(rune) +} + +// getWhitespaceString returns a string that is long enough to overwrite the default +// output from the go testing framework. +func getWhitespaceString() string { + + _, file, line, ok := runtime.Caller(1) + if !ok { + return "" + } + parts := strings.Split(file, "/") + file = parts[len(parts)-1] + + return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line))) + +} + +func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { + if len(msgAndArgs) == 0 || msgAndArgs == nil { + return "" + } + if len(msgAndArgs) == 1 { + return msgAndArgs[0].(string) + } + if len(msgAndArgs) > 1 { + return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) + } + return "" +} + +// Aligns the provided message so that all lines after the first line start at the same location as the first line. +// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). +// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the +// basis on which the alignment occurs). +func indentMessageLines(message string, longestLabelLen int) string { + outBuf := new(bytes.Buffer) + + for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { + // no need to align first line because it starts at the correct location (after the label) + if i != 0 { + // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab + outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen +1) + "\t") + } + outBuf.WriteString(scanner.Text()) + } + + return outBuf.String() +} + +type failNower interface { + FailNow() +} + +// FailNow fails test +func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + Fail(t, failureMessage, msgAndArgs...) + + // We cannot extend TestingT with FailNow() and + // maintain backwards compatibility, so we fallback + // to panicking when FailNow is not available in + // TestingT. + // See issue #263 + + if t, ok := t.(failNower); ok { + t.FailNow() + } else { + panic("test failed and t is missing `FailNow()`") + } + return false +} + +// Fail reports a failure through +func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + content := []labeledContent{ + {"Error Trace", strings.Join(CallerInfo(), "\n\r\t\t\t")}, + {"Error", failureMessage}, + } + + message := messageFromMsgAndArgs(msgAndArgs...) + if len(message) > 0 { + content = append(content, labeledContent{"Messages", message}) + } + + t.Errorf("\r" + getWhitespaceString() + labeledOutput(content...)) + + return false +} + +type labeledContent struct { + label string + content string +} + +// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: +// +// \r\t{{label}}:{{align_spaces}}\t{{content}}\n +// +// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. +// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this +// alignment is achieved, "\t{{content}}\n" is added for the output. +// +// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line. +func labeledOutput(content ...labeledContent) string { + longestLabel := 0 + for _, v := range content { + if len(v.label) > longestLabel { + longestLabel = len(v.label) + } + } + var output string + for _, v := range content { + output += "\r\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" + } + return output +} + +// Implements asserts that an object is implemented by the specified interface. +// +// assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject") +func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + + interfaceType := reflect.TypeOf(interfaceObject).Elem() + + if !reflect.TypeOf(object).Implements(interfaceType) { + return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) + } + + return true + +} + +// IsType asserts that the specified objects are of the same type. +func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + + if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { + return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) + } + + return true +} + +// Equal asserts that two objects are equal. +// +// assert.Equal(t, 123, 123, "123 and 123 should be equal") +// +// Returns whether the assertion was successful (true) or not (false). +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + + if !ObjectsAreEqual(expected, actual) { + diff := diff(expected, actual) + expected, actual = formatUnequalValues(expected, actual) + return Fail(t, fmt.Sprintf("Not equal: \n"+ + "expected: %s\n"+ + "received: %s%s", expected, actual, diff), msgAndArgs...) + } + + return true + +} + +// formatUnequalValues takes two values of arbitrary types and returns string +// representations appropriate to be presented to the user. +// +// If the values are not of like type, the returned strings will be prefixed +// with the type name, and the value will be enclosed in parenthesis similar +// to a type conversion in the Go grammar. +func formatUnequalValues(expected, actual interface{}) (e string, a string) { + if reflect.TypeOf(expected) != reflect.TypeOf(actual) { + return fmt.Sprintf("%T(%#v)", expected, expected), + fmt.Sprintf("%T(%#v)", actual, actual) + } + + return fmt.Sprintf("%#v", expected), + fmt.Sprintf("%#v", actual) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValues(t, uint32(123), int32(123), "123 and 123 should be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + + if !ObjectsAreEqualValues(expected, actual) { + diff := diff(expected, actual) + expected, actual = formatUnequalValues(expected, actual) + return Fail(t, fmt.Sprintf("Not equal: \n"+ + "expected: %s\n"+ + "received: %s%s", expected, actual, diff), msgAndArgs...) + } + + return true + +} + +// Exactly asserts that two objects are equal is value and type. +// +// assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + + aType := reflect.TypeOf(expected) + bType := reflect.TypeOf(actual) + + if aType != bType { + return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...) + } + + return Equal(t, expected, actual, msgAndArgs...) + +} + +// NotNil asserts that the specified object is not nil. +// +// assert.NotNil(t, err, "err should be something") +// +// Returns whether the assertion was successful (true) or not (false). +func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if !isNil(object) { + return true + } + return Fail(t, "Expected value not to be nil.", msgAndArgs...) +} + +// isNil checks if a specified object is nil or not, without Failing. +func isNil(object interface{}) bool { + if object == nil { + return true + } + + value := reflect.ValueOf(object) + kind := value.Kind() + if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() { + return true + } + + return false +} + +// Nil asserts that the specified object is nil. +// +// assert.Nil(t, err, "err should be nothing") +// +// Returns whether the assertion was successful (true) or not (false). +func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if isNil(object) { + return true + } + return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) +} + +var numericZeros = []interface{}{ + int(0), + int8(0), + int16(0), + int32(0), + int64(0), + uint(0), + uint8(0), + uint16(0), + uint32(0), + uint64(0), + float32(0), + float64(0), +} + +// isEmpty gets whether the specified object is considered empty or not. +func isEmpty(object interface{}) bool { + + if object == nil { + return true + } else if object == "" { + return true + } else if object == false { + return true + } + + for _, v := range numericZeros { + if object == v { + return true + } + } + + objValue := reflect.ValueOf(object) + + switch objValue.Kind() { + case reflect.Map: + fallthrough + case reflect.Slice, reflect.Chan: + { + return (objValue.Len() == 0) + } + case reflect.Struct: + switch object.(type) { + case time.Time: + return object.(time.Time).IsZero() + } + case reflect.Ptr: + { + if objValue.IsNil() { + return true + } + switch object.(type) { + case *time.Time: + return object.(*time.Time).IsZero() + default: + return false + } + } + } + return false +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Empty(t, obj) +// +// Returns whether the assertion was successful (true) or not (false). +func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + + pass := isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmpty(t, obj) { +// assert.Equal(t, "two", obj[1]) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + + pass := !isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// getLen try to get length of object. +// return (false, 0) if impossible. +func getLen(x interface{}) (ok bool, length int) { + v := reflect.ValueOf(x) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + return true, v.Len() +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// assert.Len(t, mySlice, 3, "The size of slice is not 3") +// +// Returns whether the assertion was successful (true) or not (false). +func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { + ok, l := getLen(object) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) + } + + if l != length { + return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) + } + return true +} + +// True asserts that the specified value is true. +// +// assert.True(t, myBool, "myBool should be true") +// +// Returns whether the assertion was successful (true) or not (false). +func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { + + if value != true { + return Fail(t, "Should be true", msgAndArgs...) + } + + return true + +} + +// False asserts that the specified value is false. +// +// assert.False(t, myBool, "myBool should be false") +// +// Returns whether the assertion was successful (true) or not (false). +func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { + + if value != false { + return Fail(t, "Should be false", msgAndArgs...) + } + + return true + +} + +// NotEqual asserts that the specified values are NOT equal. +// +// assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal") +// +// Returns whether the assertion was successful (true) or not (false). +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + + if ObjectsAreEqual(expected, actual) { + return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) + } + + return true + +} + +// containsElement try loop over the list check if the list includes the element. +// return (false, false) if impossible. +// return (true, false) if element was not found. +// return (true, true) if element was found. +func includeElement(list interface{}, element interface{}) (ok, found bool) { + + listValue := reflect.ValueOf(list) + elementValue := reflect.ValueOf(element) + defer func() { + if e := recover(); e != nil { + ok = false + found = false + } + }() + + if reflect.TypeOf(list).Kind() == reflect.String { + return true, strings.Contains(listValue.String(), elementValue.String()) + } + + if reflect.TypeOf(list).Kind() == reflect.Map { + mapKeys := listValue.MapKeys() + for i := 0; i < len(mapKeys); i++ { + if ObjectsAreEqual(mapKeys[i].Interface(), element) { + return true, true + } + } + return true, false + } + + for i := 0; i < listValue.Len(); i++ { + if ObjectsAreEqual(listValue.Index(i).Interface(), element) { + return true, true + } + } + return true, false + +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'") +// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'") +// assert.Contains(t, {"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'") +// +// Returns whether the assertion was successful (true) or not (false). +func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if !found { + return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'") +// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'") +// assert.NotContains(t, {"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'") +// +// Returns whether the assertion was successful (true) or not (false). +func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if found { + return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// Condition uses a Comparison to assert a complex condition. +func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { + result := comp() + if !result { + Fail(t, "Condition failed!", msgAndArgs...) + } + return result +} + +// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics +// methods, and represents a simple func that takes no arguments, and returns nothing. +type PanicTestFunc func() + +// didPanic returns true if the function passed to it panics. Otherwise, it returns false. +func didPanic(f PanicTestFunc) (bool, interface{}) { + + didPanic := false + var message interface{} + func() { + + defer func() { + if message = recover(); message != nil { + didPanic = true + } + }() + + // call the target function + f() + + }() + + return didPanic, message + +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panics(t, func(){ +// GoCrazy() +// }, "Calling GoCrazy() should panic") +// +// Returns whether the assertion was successful (true) or not (false). +func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + + if funcDidPanic, panicValue := didPanic(f); !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + } + + return true +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanics(t, func(){ +// RemainCalm() +// }, "Calling RemainCalm() should NOT panic") +// +// Returns whether the assertion was successful (true) or not (false). +func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + + if funcDidPanic, panicValue := didPanic(f); funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + } + + return true +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s") +// +// Returns whether the assertion was successful (true) or not (false). +func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + + dt := expected.Sub(actual) + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +func toFloat(x interface{}) (float64, bool) { + var xf float64 + xok := true + + switch xn := x.(type) { + case uint8: + xf = float64(xn) + case uint16: + xf = float64(xn) + case uint32: + xf = float64(xn) + case uint64: + xf = float64(xn) + case int: + xf = float64(xn) + case int8: + xf = float64(xn) + case int16: + xf = float64(xn) + case int32: + xf = float64(xn) + case int64: + xf = float64(xn) + case float32: + xf = float64(xn) + case float64: + xf = float64(xn) + default: + xok = false + } + + return xf, xok +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) +// +// Returns whether the assertion was successful (true) or not (false). +func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + + af, aok := toFloat(expected) + bf, bok := toFloat(actual) + + if !aok || !bok { + return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) + } + + if math.IsNaN(af) { + return Fail(t, fmt.Sprintf("Actual must not be NaN"), msgAndArgs...) + } + + if math.IsNaN(bf) { + return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) + } + + dt := af - bf + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta) + if !result { + return result + } + } + + return true +} + +func calcRelativeError(expected, actual interface{}) (float64, error) { + af, aok := toFloat(expected) + if !aok { + return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) + } + if af == 0 { + return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") + } + bf, bok := toFloat(actual) + if !bok { + return 0, fmt.Errorf("expected value %q cannot be converted to float", actual) + } + + return math.Abs(af-bf) / math.Abs(af), nil +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +// +// Returns whether the assertion was successful (true) or not (false). +func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + actualEpsilon, err := calcRelativeError(expected, actual) + if err != nil { + return Fail(t, err.Error(), msgAndArgs...) + } + if actualEpsilon > epsilon { + return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ + " < %#v (actual)", actualEpsilon, epsilon), msgAndArgs...) + } + + return true +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) + if !result { + return result + } + } + + return true +} + +/* + Errors +*/ + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoError(t, err) { +// assert.Equal(t, actualObj, expectedObj) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { + if err != nil { + return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) + } + + return true +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Error(t, err, "An error was expected") { +// assert.Equal(t, err, expectedError) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { + + if err == nil { + return Fail(t, "An error is expected but got nil.", msgAndArgs...) + } + + return true +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualError(t, err, expectedErrorString, "An error was expected") +// +// Returns whether the assertion was successful (true) or not (false). +func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { + if !Error(t, theError, msgAndArgs...) { + return false + } + expected := errString + actual := theError.Error() + // don't need to use deep equals here, we know they are both strings + if expected != actual { + return Fail(t, fmt.Sprintf("Error message not equal:\n"+ + "expected: %q\n"+ + "received: %q", expected, actual), msgAndArgs...) + } + return true +} + +// matchRegexp return true if a specified regexp matches a string. +func matchRegexp(rx interface{}, str interface{}) bool { + + var r *regexp.Regexp + if rr, ok := rx.(*regexp.Regexp); ok { + r = rr + } else { + r = regexp.MustCompile(fmt.Sprint(rx)) + } + + return (r.FindStringIndex(fmt.Sprint(str)) != nil) + +} + +// Regexp asserts that a specified regexp matches a string. +// +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + + match := matchRegexp(rx, str) + + if !match { + Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) + } + + return match +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + match := matchRegexp(rx, str) + + if match { + Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) + } + + return !match + +} + +// Zero asserts that i is the zero value for its type and returns the truth. +func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { + return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) + } + return true +} + +// NotZero asserts that i is not the zero value for its type and returns the truth. +func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { + return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) + } + return true +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +// +// Returns whether the assertion was successful (true) or not (false). +func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { + var expectedJSONAsInterface, actualJSONAsInterface interface{} + + if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) + } + + if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) + } + + return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) +} + +func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { + t := reflect.TypeOf(v) + k := t.Kind() + + if k == reflect.Ptr { + t = t.Elem() + k = t.Kind() + } + return t, k +} + +// diff returns a diff of both values as long as both are of the same type and +// are a struct, map, slice or array. Otherwise it returns an empty string. +func diff(expected interface{}, actual interface{}) string { + if expected == nil || actual == nil { + return "" + } + + et, ek := typeAndKind(expected) + at, _ := typeAndKind(actual) + + if et != at { + return "" + } + + if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array { + return "" + } + + e := spewConfig.Sdump(expected) + a := spewConfig.Sdump(actual) + + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(e), + B: difflib.SplitLines(a), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + + return "\n\nDiff:\n" + diff +} + +var spewConfig = spew.ConfigState{ + Indent: " ", + DisablePointerAddresses: true, + DisableCapacities: true, + SortKeys: true, +} diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go new file mode 100644 index 0000000..c9dccc4 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/doc.go @@ -0,0 +1,45 @@ +// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. +// +// Example Usage +// +// The following is a complete example using assert in a standard test function: +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(t, a, b, "The two words should be the same.") +// +// } +// +// if you assert many times, use the format below: +// +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// assert := assert.New(t) +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(a, b, "The two words should be the same.") +// } +// +// Assertions +// +// Assertions allow you to easily write test code, and are global funcs in the `assert` package. +// All assertion functions take, as the first argument, the `*testing.T` object provided by the +// testing framework. This allows the assertion funcs to write the failings and other details to +// the correct place. +// +// Every assertion function also takes an optional string message as the final argument, +// allowing custom error messages to be appended to the message the assertion method outputs. +package assert diff --git a/vendor/github.com/stretchr/testify/assert/errors.go b/vendor/github.com/stretchr/testify/assert/errors.go new file mode 100644 index 0000000..ac9dc9d --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/errors.go @@ -0,0 +1,10 @@ +package assert + +import ( + "errors" +) + +// AnError is an error instance useful for testing. If the code does not care +// about error specifics, and only needs to return the error for example, this +// error should be used to make the test code more readable. +var AnError = errors.New("assert.AnError general error for testing") diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/vendor/github.com/stretchr/testify/assert/forward_assertions.go new file mode 100644 index 0000000..b867e95 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/forward_assertions.go @@ -0,0 +1,16 @@ +package assert + +// Assertions provides assertion methods around the +// TestingT interface. +type Assertions struct { + t TestingT +} + +// New makes a new Assertions object for the specified TestingT. +func New(t TestingT) *Assertions { + return &Assertions{ + t: t, + } +} + +//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go new file mode 100644 index 0000000..fa7ab89 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -0,0 +1,106 @@ +package assert + +import ( + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "strings" +) + +// httpCode is a helper that returns HTTP code of the response. It returns -1 +// if building a new request fails. +func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int { + w := httptest.NewRecorder() + req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if err != nil { + return -1 + } + handler(w, req) + return w.Code +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { + code := httpCode(handler, method, url, values) + if code == -1 { + return false + } + return code >= http.StatusOK && code <= http.StatusPartialContent +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { + code := httpCode(handler, method, url, values) + if code == -1 { + return false + } + return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { + code := httpCode(handler, method, url, values) + if code == -1 { + return false + } + return code >= http.StatusBadRequest +} + +// HTTPBody is a helper that returns HTTP body of the response. It returns +// empty string if building a new request fails. +func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { + w := httptest.NewRecorder() + req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if err != nil { + return "" + } + handler(w, req) + return w.Body.String() +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool { + body := HTTPBody(handler, method, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if !contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return contains +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool { + body := HTTPBody(handler, method, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return !contains +} diff --git a/vendor/vendor.json b/vendor/vendor.json new file mode 100644 index 0000000..792d169 --- /dev/null +++ b/vendor/vendor.json @@ -0,0 +1,57 @@ +{ + "comment": "", + "ignore": "test", + "package": [ + { + "checksumSHA1": "AcWCvzWyeJdc1Iw/Gw6upQPsroE=", + "path": "github.com/BurntSushi/xgb", + "revision": "27f122750802c950b2c869a5b63dafcf590ced95", + "revisionTime": "2016-05-22T18:18:43Z" + }, + { + "checksumSHA1": "i8V/eYv4tGJs3tL6lpz7IEvRYVs=", + "path": "github.com/BurntSushi/xgb/xproto", + "revision": "27f122750802c950b2c869a5b63dafcf590ced95", + "revisionTime": "2016-05-22T18:18:43Z" + }, + { + "checksumSHA1": "0i0VqgwQdvY01/RdxtRu6MCGwZs=", + "path": "github.com/BurntSushi/xgb/xtest", + "revision": "27f122750802c950b2c869a5b63dafcf590ced95", + "revisionTime": "2016-05-22T18:18:43Z" + }, + { + "checksumSHA1": "DuHM9UBDn6AHdGqYDMZZqzFMOkI=", + "path": "github.com/bendahl/uinput", + "revision": "050ec524df761f5a128a5bb9bb5b7609f1886f21", + "revisionTime": "2017-06-20T19:50:18Z" + }, + { + "checksumSHA1": "OFu4xJEIjiI8Suu+j/gabfp+y6Q=", + "origin": "github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew", + "path": "github.com/davecgh/go-spew/spew", + "revision": "2402e8e7a02fc811447d11f881aa9746cdc57983", + "revisionTime": "2016-12-17T20:04:45Z" + }, + { + "checksumSHA1": "B8TpaihN7IAVweKEqETyEisecbw=", + "path": "github.com/gvalkov/golang-evdev", + "revision": "87c03aa1a370124ec5a5fac733a629e0f9acd9a6", + "revisionTime": "2016-09-25T11:10:49Z" + }, + { + "checksumSHA1": "zKKp5SZ3d3ycKe4EKMNT0BqAWBw=", + "origin": "github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib", + "path": "github.com/pmezard/go-difflib/difflib", + "revision": "2402e8e7a02fc811447d11f881aa9746cdc57983", + "revisionTime": "2016-12-17T20:04:45Z" + }, + { + "checksumSHA1": "c4Fu2xN9Wt2qhupbwp0atOtragE=", + "path": "github.com/stretchr/testify/assert", + "revision": "2402e8e7a02fc811447d11f881aa9746cdc57983", + "revisionTime": "2016-12-17T20:04:45Z" + } + ], + "rootPath": "github.com/abourget/shuttle-go" +} diff --git a/xinput.go b/xinput.go index b5fe248..dd8bd56 100644 --- a/xinput.go +++ b/xinput.go @@ -9,7 +9,7 @@ import ( ) var xinputDevices = []*regexp.Regexp{ - regexp.MustCompile(`↳ Contour Design ShuttlePRO v2\s+id=(\d)\s`), + regexp.MustCompile(`↳ Contour Design ShuttlePRO v2\s+id=(\d+)\s`), } func disableXInputPointer() {