A utility library to make use of the X Go Binding easier. (Implements EWMH and ICCCM specs, key binding support, etc.)

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

Owner
Andrew Gallant
I love to code.
Andrew Gallant
Comments
  • Resize issues and Geometry values

    Resize issues and Geometry values

    Hi !

    I am trying to resize and move window using xgbutil and facing some issues about it. I am running i3wm and use pkg.go.dev/go.i3wm.org/i3/ to obtain the focused window ID. Then I resize the window using one of the several methods provided by xgbutil.

    My issue is : I have a window of random size, I want to move it and set it to a specific size, let's say 640x360. When I run one time my program, the window is moved in the correct place however the size is not correct. Geometry functions report a bogus size. If I run a second time the program immediately after, I can see the window changing a liittle bit its size again to finally get the correct size. Geometry functions returns the same value as before but this time it is correct. Subsquent run does not change the size anymore.

    I have printed the geometry of the window before and after the call to the resize function and can see the second time that the size was incorrect (geometry reports the incorrect size). I don't understand why the geometry after the call in the first run is incorrect though.

    Let's wrap-up: I create two sets of objects to be sure I am not reusing bufferized values. My code is

    xgbUtil, _ := xgbutil.NewConn()
    xWin := xwindow.New(xgbUtil, windID)
    geom, _ := xWin.Geometry()
    fmt.Println("Before ", uint(geom.Width()))
    ewmh.MoveresizeWindow(xgbUtil, windID, 0, 0, 640,360)
    xgbUtil2, _ := xgbutil.NewConn()
    xWin2 := xwindow.New(xgbUtil2, windID)
    geom2, _ := xWin2.Geometry()
    fmt.Println("After  ", uint(geom2.Width()))
    

    First run I got:

    Before 789 <= Random initial width of the window
    After 640 <= This is incorrect, the window is smaller
    

    I do not touch anything and a rerun the program, I got:

    Before 637 <= This shall have been in the "After" value on the first run
    After 640 <= Now this is correct !
    

    I am a little bit confused in front of the multiple function to resize a window. I found: ewmh.MoveresizeWindow ewmh.MoveresizeWindowExtra ewmh.WmMoveresizeWindow ewmh.WmMoveresizeWindowExtra ewmh.ResizeWindow xwindow.Resize xwindow.MoveResize xwindow.WMResize xwindow.WMMoveResize

    I understand some of the differences (such as between Move and MoveResize) but I do not understand the difference between Resize and WMResize for example.

  • Transparent Child Window

    Transparent Child Window

    How do I create a transparent child window ?

    This is how I create a child window under a root window

    win, err := xwindow.Generate(xu)
    win.Create(parent, X,Y, Width,Height, xproto.CwBackPixel, 0xfffff)
    

    Is it something to do with the valuemasks xproto.CwBackPixel ?

    Any pointer will be very helpful. Thanks.

  • example window-gradient fails

    example window-gradient fails

    example window-gradient fails

    The example window-graient fails with a large number of xgraphics issues.

    Errors

    ../../xgraphics/image.go:32: imported and not used: "code.google.com/p/graphics-go/graphics" ../../xgraphics/text.go:10: emptyarchive redeclared as imported package name previous declaration at ../../xgraphics/text.go:9 ../../xgraphics/text.go:10: imported and not used: "code.google.com/p/freetype-go/freetype/truetype" ../../xgraphics/text.go:24: undefined: truetype ../../xgraphics/text.go:54: undefined: truetype ../../xgraphics/text.go:63: undefined: freetype ../../xgraphics/text.go:63: undefined: truetype ../../xgraphics/text.go:73: undefined: truetype ../../xgraphics/text.go:88: undefined: truetype ../../xgraphics/util.go:10: imported and not used: "code.google.com/p/graphics-go/graphics" ../../xgraphics/text.go:88: too many errors

    These same errors appear any time you attempt to load xgraphics.

  • [Question] Support for simulating keypresses?

    [Question] Support for simulating keypresses?

    Hello! Thanks for this library and for taking the time to write out the examples as they have been very helpful. Currently I'm trying to make a bare bones a simple text expander. The first part was easy to do modifying the example the keypress-english examples so I could listen for the text. I didn't any examples for simulating a keypress and was wondering if this library supports that and if not where to start looking for something like that? I have some very simple working C code:

    #include <stdio.h>
    #include <X11/X.h>
    #include <X11/Xlib.h>
    #include <X11/extensions/XTest.h>
    #include <unistd.h>
    
    #define XK_c                             0x0063
    #define XK_d                             0x0064
    #define XK_h                             0x0068
    #define XK_o                             0x006f
    #define XK_y                             0x0079 
    #define XK_at                            0x0040
    #define XK_Shift_L                       0xffe1
    
    int main() {
      Display *dpy;
      dpy = XOpenDisplay(NULL);
      sleep(2);
    
      KeyCode code = XKeysymToKeycode(dpy, XK_c);
      XTestFakeKeyEvent(dpy, code, True, CurrentTime);
      XTestFakeKeyEvent(dpy, code, False, CurrentTime);
      code = XKeysymToKeycode(dpy, XK_o);
      XTestFakeKeyEvent(dpy, code, True, CurrentTime);
      XTestFakeKeyEvent(dpy, code, False, CurrentTime);
      code = XKeysymToKeycode(dpy, XK_d);
      XTestFakeKeyEvent(dpy, code, True, CurrentTime);
      XTestFakeKeyEvent(dpy, code, False, CurrentTime);
      code = XKeysymToKeycode(dpy, XK_y);
      XTestFakeKeyEvent(dpy, code, True, CurrentTime);
      XTestFakeKeyEvent(dpy, code, False, CurrentTime);
    
      // Make sure to send shift
      code = XKeysymToKeycode(dpy, XK_Shift_L);
      XTestFakeKeyEvent(dpy, code, True, CurrentTime);
      code = XKeysymToKeycode(dpy, XK_at);
      XTestFakeKeyEvent(dpy, code, True, CurrentTime);
      XTestFakeKeyEvent(dpy, code, False, CurrentTime);
      code = XKeysymToKeycode(dpy, XK_Shift_L);
      XTestFakeKeyEvent(dpy, code, False, CurrentTime);
      // No more shift
      //
      code = XKeysymToKeycode(dpy, XK_h);
      XTestFakeKeyEvent(dpy, code, True, CurrentTime);
      XTestFakeKeyEvent(dpy, code, False, CurrentTime);
    
      XFlush( dpy );
      XCloseDisplay( dpy );
    
      return 0;
    }
    

    After that I updated this code to use something a bit more robust so I could call the C code from go with the following:

    #include <stdio.h>
    #include <X11/X.h>
    #include <X11/Xlib.h>
    #include <X11/extensions/XTest.h>
    
    
    int x11_key(char *zh){
      Display *dpy;
      dpy = XOpenDisplay(NULL);
    
      KeySym sym = XStringToKeysym(zh);
      int min, max, numcodes;
      XDisplayKeycodes(dpy,&min,&max);
      KeySym *keysym;
      keysym = XGetKeyboardMapping(dpy,min,max-min+1,&numcodes);
      keysym[(max-min-1)*numcodes]=sym;
      XChangeKeyboardMapping(dpy,min,numcodes,keysym,(max-min));
      XFree(keysym);
      XFlush( dpy );
      KeyCode code = XKeysymToKeycode(dpy,sym);
      XTestFakeKeyEvent(dpy, code, True, 1);
      XTestFakeKeyEvent(dpy, code, False, 1);
    
      XFlush( dpy );
      XCloseDisplay( dpy );
    
      return 0;
    }
    

    Which worked pretty well but when I would send a string like [email protected] the @ symbol would get messed up in programs other that the terminal I was running the code in. I searched around and saw the comment posted on https://stackoverflow.com/questions/26446184/control-the-mouse-and-keyboard-golang that said For X11 at least, there's no reason to use a C library. XGB is a native implementation of the X client protocol. which lead me here but I couldn't find and examples that simulated keypresses.

  • [Patch] Add a simple hook system to allow interception of events.

    [Patch] Add a simple hook system to allow interception of events.

    This is a simple patch that adds hooks to the xevent main loop, allowing handling of messages that don't conform to the package's routing mechanics

    Hooks return true to allow the message to be processed as normal, false to abort processing of the event, presumably to implement it all in the hook's callback.

    http://amanda.darkdna.net/p/1acba

  • png files (gopher subpackage) double-gzip'd

    png files (gopher subpackage) double-gzip'd

    The png format already uses zlib internally for compression -- compressing it again is very unlikely to provide additional compression, and requires additional processing (once for your decompression, another time for the image library to decompress the png's pixels).

    Large byte slices may also cause pathological behavior in the gc compiler (memory use ballooning). https://github.com/jteeuwen/go-bindata specializes in making sure the given binary file is compiled into a readonly memory segment without the major adverse effects -- though again, gzipping png files is best avoided.

  • WTFPL not supported by go.dev / no LICENSE file

    WTFPL not supported by go.dev / no LICENSE file

    Go.dev will not show documentation for this library because there is no LICENSE file and the WTFPL is not in their supported list.

    Perhaps you wish to use the Unlicense?

    You can find more information on this issue here.

  • xgraphics: package depends on code.google.com/p/jamslam-freetype-go/freetype

    xgraphics: package depends on code.google.com/p/jamslam-freetype-go/freetype

    The package "code.google.com/p/jamslam-freetype-go/freetype" is going to disappear in January (last I heard). At that point the xgraphics package will not build.

    It seems that the package requires the Context.MeasureString method which iirc was not available in "code.google.com/p/freetype-go/freetype".Context. I assume this was the original reason the "jamslam-" variant was used.

    I have had similar requirements in the past. And I have used "jamslam" to meet them. Most recently when dealing with and trying to avoid code.google.com I found that I could achieve the MeasureString functionality by combining "github.com/golang/freetype" and "golang.org/x/image/font". You can look at my code. There is some weird rendering stuff going on in that program. But if you just trace back the types from the call site it should be fairly straightforward.

    I think what it would boil down to in xgraphics/text.go would be something like the following (with some additional logic to create a font.Drawer):

    w := f.MeasureString(text)
    h := int(c.PointToFixed(fontSize) >> 6)
    

    The height calculation is basically the same thing that "jamslam" is doing.

  • Improved performance of XPaintRects

    Improved performance of XPaintRects

    xgraphics.Image.xdraw (called by XPaintRects) has rather poor performance when called on a subimage.

    Without any change I can get it to push ~37'000'000 pixel/second. Just swapping the x and y indexes on the loop that copies to the data buffer I can get to ~60'000'000 pixel/second. With the change in this commit, that calls copy on whole rows xdraw will push ~197'000'000 pixel/second, a 5x improvement on the original.

  • add new api: NewConnXgb. We can use the specific xgb.Conn to init a xgbutil.XUtil

    add new api: NewConnXgb. We can use the specific xgb.Conn to init a xgbutil.XUtil

    Add a new api: NewConnXgb. We can use a specific/custom xgb.Conn to initialize a xgbutil.Xutil.

    example:

    xgbConn, _ := xgb.NewConnDisplay(":1")
    X, _ := xgbutil.NewConnXgb(xgbConn)
    

    Meanwhile, the NewConn and NewConnDisplay calls the NewConnXgb.

  • Image.Text and non-English chars.

    Image.Text and non-English chars.

    The Text helper function seems to be rendering foreign chars incorrectly. For example (should be śledź): sledz

    It's using a slightly modified _examples/draw-text code (changed the text to be rendered, of course). Tried with different fonts, all the same.

    By the looking of this, I think it might be calculating the extents wrong. Which will make it a freetype-go bug, I guess. In such case, feel free to close this one.

  • More functions for working with modifiers

    More functions for working with modifiers

    Currently, if you don't want to do any masking yourself, there's only one function that you can use (that I know of), and that's keybind.ModifierString. This functions does several things you might not want:

    • It returns the modifiers connected with -
    • It returns the modifiers as strings, which isn't very efficient

    Now, this isn't to say it's a bad function, but rather that it isn't sufficient as the only function.

  • LookupString segfault on linux

    LookupString segfault on linux

    output:

    panic: runtime error: invalid memory address or nil pointer dereference [recovered]
            panic: runtime error: invalid memory address or nil pointer dereference
    [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x5911be]
    
    goroutine 19 [running]:
    testing.tRunner.func1.1(0x5b4dc0, 0x733ee0)
            /usr/lib/go-1.15/src/testing/testing.go:1057 +0x30d
    testing.tRunner.func1(0xc000082900)
            /usr/lib/go-1.15/src/testing/testing.go:1060 +0x41a
    panic(0x5b4dc0, 0x733ee0)
            /usr/lib/go-1.15/src/runtime/panic.go:969 +0x175
    github.com/BurntSushi/xgbutil/keybind.KeysymGetWithMap(...)
            /home/binarycat/go/src/github.com/BurntSushi/xgbutil/keybind/keybind.go:260
    github.com/BurntSushi/xgbutil/keybind.KeysymGet(...)
            /home/binarycat/go/src/github.com/BurntSushi/xgbutil/keybind/keybind.go:251
    github.com/BurntSushi/xgbutil/keybind.interpretSymList(0xc0000fa140, 0x5ab836, 0x620101, 0xc000129e98, 0x59200d, 0x9, 0xc000129e80, 0x7208c0, 0x5ebcfd, 0x4)
            /home/binarycat/go/src/github.com/BurntSushi/xgbutil/keybind/encoding.go:87 +0x3e
    github.com/BurntSushi/xgbutil/keybind.LookupString(0xc0000fa140, 0x360010, 0x4, 0x6c68b0)
            /home/binarycat/go/src/github.com/BurntSushi/xgbutil/keybind/encoding.go:34 +0x3e
    github.com/lolbinarycat/dprefix.GetString(0x5f525ef0, 0xc000030770)
            /home/binarycat/go/src/github.com/lolbinarycat/dprefix/main.go:30 +0x8c
    github.com/lolbinarycat/dprefix.TestGetString(0xc000082900)
            /home/binarycat/go/src/github.com/lolbinarycat/dprefix/main_test.go:27 +0x26
    testing.tRunner(0xc000082900, 0x5fd808)
            /usr/lib/go-1.15/src/testing/testing.go:1108 +0xef
    created by testing.(*T).Run
            /usr/lib/go-1.15/src/testing/testing.go:1159 +0x386
    

    uname -a:

    Linux binarycat 4.19.0-10-amd64 #1 SMP Debian 4.19.132-1 (2020-07-24) x86_64 GNU/Linux
    

    go env:

    GO111MODULE=""
    GOARCH="amd64"
    GOBIN=""
    GOCACHE="/home/binarycat/.cache/go-build"
    GOENV="/home/binarycat/.config/go/env"
    GOEXE=""
    GOFLAGS=""
    GOHOSTARCH="amd64"
    GOHOSTOS="linux"
    GOINSECURE=""
    GOMODCACHE="/home/binarycat/go/pkg/mod"
    GONOPROXY=""
    GONOSUMDB=""
    GOOS="linux"
    GOPATH="/home/binarycat/go"
    GOPRIVATE=""
    GOPROXY="https://proxy.golang.org,direct"
    GOROOT="/usr/lib/go-1.15"
    GOSUMDB="sum.golang.org"
    GOTMPDIR=""
    GOTOOLDIR="/usr/lib/go-1.15/pkg/tool/linux_amd64"
    GCCGO="/usr/bin/gccgo"
    AR="ar"
    CC="gcc"
    CXX="g++"
    CGO_ENABLED="1"
    GOMOD=""
    CGO_CFLAGS="-g -O2"
    CGO_CPPFLAGS=""
    CGO_CXXFLAGS="-g -O2"
    CGO_FFLAGS="-g -O2"
    CGO_LDFLAGS="-g -O2"
    PKG_CONFIG="pkg-config"
    GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build338105219=/tmp/go-build -gno-record-gcc-switches"
    
  • [question] mousebind -- button chords

    [question] mousebind -- button chords

    Thank you for this library, it's real nice, made things so much easier

    Mousebind docs say mouse buttons can be modifiers, so mouse chords should work.

    But running this code:

    package main
    
    import (
    	"log"
    
    	"github.com/BurntSushi/xgbutil"
    	"github.com/BurntSushi/xgbutil/mousebind"
    	"github.com/BurntSushi/xgbutil/xevent"
    )
    
    func main() {
    	X, err := xgbutil.NewConn()
    	if err != nil {
    		log.Fatal(err)
    	}
    	mousebind.Initialize(X)
    
    
    	cb1 := mousebind.ButtonPressFun(
    		func(X *xgbutil.XUtil, e xevent.ButtonPressEvent) {
    			log.Println("Button press!")
    		})
    
    	err = cb1.Connect(X, X.RootWin(), "button3-1", false, true)
    	if err != nil {
    		log.Println(err)
    	}
    
    	xevent.Main(X)
    }
    

    Produces this error:

    Could not bind 'button3-1' because: 
    BadValue {NiceName: Value, Sequence: 5, BadValue: 1024, MinorOpcode: 0, MajorOpcode: 28}
    

    Any kind of help for solving this would be much appreciated. Thank you again for all your great work

  • [question] Fall back fonts.

    [question] Fall back fonts.

    How would I go about loading fallback fonts, for example I'm using a ttf font that doesn't have Japanese characters, so I want a different to be used whenever there is a Japanese character.

  • [feature request] Add support for pcf fonts.

    [feature request] Add support for pcf fonts.

    See title, support for pcf fonts would be very nice, expecially since many terminal like applications make use of them and because it doesn't seem to be possible to draw bitmap fonts using freetype-go.

    I've looked around and this seems to be the only pcf library for go: https://github.com/nareix/pcf

Qt binding for Go (Golang) with support for Windows / macOS / Linux / FreeBSD / Android / iOS / Sailfish OS / Raspberry Pi / AsteroidOS / Ubuntu Touch / JavaScript / WebAssembly

Introduction Qt is a free and open-source widget toolkit for creating graphical user interfaces as well as cross-platform applications that run on var

Jan 2, 2023
The X Go Binding is a low-level API to communicate with the X server. It is modeled on XCB and supports many X extensions.

Note that this project is largely unmaintained as I don't have the time to do or support more development. Please consider using this fork instead: ht

Dec 29, 2022
Go binding for GTK
Go binding for GTK

go-gtk WHATS Go bindings for GTK SCREENSHOT INSTALL You can experiment with go-gtk by running the various example programs: git clone https://github.c

Jan 5, 2023
Simple QML binding for Go

Qamel Qamel is a simple QML binding for Go, heavily inspired by therecipe/qt. This package only binds Qt's classes that used for creating a simple QML

Jan 3, 2023
SDL2 binding for Go

SDL2 binding for Go go-sdl2 is SDL2 wrapped for Go users. It enables interoperability between Go and the SDL2 library which is written in C. That mean

Dec 30, 2022
Qt binding for Go (Golang) aims get Go's compile speed again.

qt.go Qt5 binding for Go (Golang) without CGO that aims to achieve Go's native compile speeds. Instead of using common bindings and heavy C++ wrapper

Dec 19, 2022
Odile is a simple GUI for the croc utility by Schollz.
Odile is a simple GUI for the croc utility by Schollz.

Odile Odile is a simple GUI for the croc utility by Schollz. This program uses Fyne, a UI toolkit written in Go, as the graphical interface. Effort wa

Dec 17, 2022
QML support for the Go language

QML support for the Go language Documentation The introductory documentation as well as the detailed API documentation is available at gopkg.in/qml.v1

Dec 19, 2022
Tiny cross-platform webview library for C/C++/Golang. Uses WebKit (Gtk/Cocoa) and Edge (Windows)

webview A tiny cross-platform webview library for C/C++/Golang to build modern cross-platform GUIs. Also, there are Rust bindings, Python bindings, Ni

Dec 28, 2022
a cross platfrom Go library to place an icon and menu in the notification area

systray is a cross-platform Go library to place an icon and menu in the notification area. Features Supported on Windows, macOS, and Linux Menu items

Dec 27, 2022
Go cross-platform library for displaying dialogs and input boxes

dlgs dlgs is a cross-platform library for displaying dialogs and input boxes. Installation go get -u github.com/gen2brain/dlgs Documentation Document

Dec 24, 2022
Tiny cross-platform webview library for C/C++/Golang. Uses WebKit (Gtk/Cocoa) and Edge (Windows)

webview A tiny cross-platform webview library for C/C++/Golang to build modern cross-platform GUIs. Also, there are Rust bindings, Python bindings, Ni

Jan 1, 2023
An experimental Go cross platform UI library.

GXUI - A Go cross platform UI library. Notice: Unfortunately due to a shortage of hours in a day, GXUI is no longer maintained. If you're looking for

Jan 6, 2023
Platform-native GUI library for Go.

ui: platform-native GUI library for Go This is a library that aims to provide simple GUI software development in Go. It is based on my libui, a simple

Jan 9, 2023
:traffic_light: Go bindings for libappindicator3 C library

go-appindicator Go bindings for libappindicator3 C library. Libappindicator is a library to allow applications to export a menu into the Unity Menu ba

Jun 19, 2022
Cross-platform Go library to place an icon in the host operating system's taskbar.

trayhost Package trayhost is a cross-platform Go library to place an icon in the host operating system's taskbar. Platform Support macOS - Fully imple

Nov 6, 2022
Common library for Go GUI apps on Windows
Common library for Go GUI apps on Windows

winc Common library for Go GUI apps on Windows. It is for Windows OS only. This makes library smaller than some other UI libraries for Go.

Dec 12, 2022
Windows GUI library for Go (Golang). Comes with a graphical UI designer.

Version 2 Please go to Version 2 of this library for the latest version. Windows GUI Library This is a pure Go library to create native Windows GUIs.

Jan 1, 2023
Go wrapper library for "Dear ImGui" (https://github.com/ocornut/imgui)
Go wrapper library for

Dear ImGui for Go This library is a Go wrapper for Dear ImGui. This wrapper started as a special-purpose wrapper for use within InkyBlackness. However

Jan 2, 2023