Initial commit

This commit is contained in:
eleksir
2024-01-06 18:33:44 +03:00
commit d85dc5d5bb
657 changed files with 262300 additions and 0 deletions

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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