aboutsummaryrefslogtreecommitdiff
path: root/xft.go
diff options
context:
space:
mode:
authorcrecher <crecher@crecher.net>2026-10-19 17:02:47 +0200
committercrecher <crecher@crecher.net>2026-10-19 17:02:47 +0200
commit4539e476b6644e961a4a96e3253c615bc4673b0c (patch)
treeea39d68fa6f5c5cb643e95ce78bdfbcc53812615 /xft.go
parent1c631b6c718e572cb4a38b4aa0f30e198818a67a (diff)
downloadwm-4539e476b6644e961a4a96e3253c615bc4673b0c.tar.gz
wm-4539e476b6644e961a4a96e3253c615bc4673b0c.zip
stuff idk i dont remember when i even made these changes tbh
Diffstat (limited to 'xft.go')
-rw-r--r--xft.go131
1 files changed, 131 insertions, 0 deletions
diff --git a/xft.go b/xft.go
new file mode 100644
index 0000000..73ab52b
--- /dev/null
+++ b/xft.go
@@ -0,0 +1,131 @@
+package main
+
+/*
+#cgo pkg-config: xft xrender x11 fontconfig
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/Xft/Xft.h>
+
+static Display *_dpy;
+static XftDraw *_drw;
+static XftFont *_ft;
+static Visual *_vis;
+static Colormap _cmap;
+static XftColor _fg;
+static int _scr;
+
+static int wm_xft_init(const char *pattern)
+{
+ int event_basep, error_basep;
+ _dpy = XOpenDisplay(NULL);
+ if (!_dpy)
+ return -1;
+ if (!XRenderQueryExtension(_dpy, &event_basep, &error_basep))
+ return -3;
+ XftInit(NULL);
+ _scr = DefaultScreen(_dpy);
+ _vis = DefaultVisual(_dpy, _scr);
+ _cmap = DefaultColormap(_dpy, _scr);
+ _ft = XftFontOpenName(_dpy, _scr, pattern);
+ if (!_ft)
+ return -2;
+ return 0;
+}
+
+static void wm_xft_setfg(unsigned int px)
+{
+ XRenderColor c;
+ c.red = ((px >> 16) & 0xff) << 8;
+ c.green = ((px >> 8) & 0xff) << 8;
+ c.blue = (px & 0xff) << 8;
+ c.alpha = 0xffff;
+ XftColorAllocValue(_dpy, _vis, _cmap, &c, &_fg);
+}
+
+static int wm_xft_width(const char *s, int n)
+{
+ XGlyphInfo gi;
+ XftTextExtentsUtf8(_dpy, _ft, (const FcChar8 *)s, n, &gi);
+ return gi.xOff;
+}
+
+static void wm_xft_draw(unsigned int win, int x, int y,
+ const char *s, int n, unsigned int fg)
+{
+ if (!_dpy || !_ft || !win)
+ return;
+ if (!_drw)
+ _drw = XftDrawCreate(_dpy, (Drawable)win, _vis, _cmap);
+ if (!_drw)
+ return;
+ XftDrawChange(_drw, (Drawable)win);
+ wm_xft_setfg(fg);
+ XftDrawStringUtf8(_drw, &_fg, _ft, x, y, (const FcChar8 *)s, n);
+ XFlush(_dpy);
+}
+
+static int wm_xft_ascent(void) { return _ft ? _ft->ascent : 0; }
+static int wm_xft_descent(void) { return _ft ? _ft->descent : 0; }
+*/
+import "C"
+
+import (
+ "unsafe"
+
+ "github.com/BurntSushi/xgb/xproto"
+)
+
+var xftOK bool
+
+func xftInit(pattern string) error {
+ cp := C.CString(pattern)
+ defer C.free(unsafe.Pointer(cp))
+
+ switch rc := int(C.wm_xft_init(cp)); rc {
+ case 0:
+ xftOK = true
+ return nil
+ case -1:
+ return errXftNoDisplay
+ case -2:
+ return errXftNoFont
+ default:
+ return errXftNoRender
+ }
+}
+
+var (
+ errXftNoDisplay = errXft("xft: cannot open display")
+ errXftNoFont = errXft("xft: cannot load font pattern")
+ errXftNoRender = errXft("xft: no RENDER extension")
+)
+
+type errXft string
+
+func (e errXft) Error() string { return string(e) }
+
+func xftTextWidth(s string) int {
+ if !xftOK {
+ return 0
+ }
+ cs := C.CString(s)
+ defer C.free(unsafe.Pointer(cs))
+ return int(C.wm_xft_width(cs, C.int(len(s))))
+}
+
+func xftDrawText(win xproto.Window, x, baseline int, s string, fg uint32) {
+ if !xftOK || win == 0 {
+ return
+ }
+ cs := C.CString(s)
+ defer C.free(unsafe.Pointer(cs))
+ C.wm_xft_draw(C.uint(win), C.int(x), C.int(baseline), cs, C.int(len(s)), C.uint(fg))
+}
+
+func xftMetrics() (ascent, descent int) {
+ if !xftOK {
+ return 0, 0
+ }
+ return int(C.wm_xft_ascent()), int(C.wm_xft_descent())
+}