diff options
Diffstat (limited to 'prototypes')
| -rw-r--r-- | prototypes/xgb-xrender.go | 176 | 
1 files changed, 176 insertions, 0 deletions
| diff --git a/prototypes/xgb-xrender.go b/prototypes/xgb-xrender.go new file mode 100644 index 0000000..73b5fed --- /dev/null +++ b/prototypes/xgb-xrender.go @@ -0,0 +1,176 @@ +package main + +import ( +	"github.com/BurntSushi/xgb" +	"github.com/BurntSushi/xgb/render" +	"github.com/BurntSushi/xgb/xproto" +	"log" +	"math/rand" +) + +func F64ToFixed(f float64) render.Fixed { return render.Fixed(f * 65536) } +func FixedToF64(f render.Fixed) float64 { return float64(f) / 65536 } + +func main() { +	X, err := xgb.NewConn() +	if err != nil { +		log.Fatalln(err) +	} + +	if err := render.Init(X); err != nil { +		log.Fatalln(err) +	} + +	setup := xproto.Setup(X) +	screen := setup.DefaultScreen(X) + +	var visual xproto.Visualid +	var depth byte +	for _, i := range screen.AllowedDepths { +		if i.Depth == 32 { +			// TODO: Could/should check other parameters. +			for _, v := range i.Visuals { +				if v.Class == xproto.VisualClassTrueColor { +					visual = v.VisualId +					depth = i.Depth +					break +				} +			} +		} +	} +	if visual == 0 { +		log.Fatalln("cannot find an RGBA TrueColor visual") +	} + +	mid, err := xproto.NewColormapId(X) +	if err != nil { +		log.Fatalln(err) +	} + +	_ = xproto.CreateColormap( +		X, xproto.ColormapAllocNone, mid, screen.Root, visual) + +	wid, err := xproto.NewWindowId(X) +	if err != nil { +		log.Fatalln(err) +	} + +	// Border pixel and colormap are required when depth differs from parent. +	_ = xproto.CreateWindow(X, depth, wid, screen.Root, +		0, 0, 500, 500, 0, xproto.WindowClassInputOutput, +		visual, xproto.CwBorderPixel|xproto.CwColormap, +		[]uint32{0, uint32(mid)}) + +	// This could be included in CreateWindow parameters. +	_ = xproto.ChangeWindowAttributes(X, wid, +		xproto.CwBackPixel|xproto.CwEventMask, []uint32{0x80808080, +			xproto.EventMaskStructureNotify | xproto.EventMaskKeyPress | +				xproto.EventMaskExposure}) + +	title := []byte("Gradient") +	_ = xproto.ChangeProperty(X, xproto.PropModeReplace, wid, xproto.AtomWmName, +		xproto.AtomString, 8, uint32(len(title)), title) + +	_ = xproto.MapWindow(X, wid) + +	pformats, err := render.QueryPictFormats(X).Reply() +	if err != nil { +		log.Fatalln(err) +	} + +	// Similar to XRenderFindVisualFormat. +	// The DefaultScreen is almost certain to be zero. +	var pformat render.Pictformat +	for _, pd := range pformats.Screens[X.DefaultScreen].Depths { +		// This check seems to be slightly extraneous. +		if pd.Depth != depth { +			continue +		} +		for _, pv := range pd.Visuals { +			if pv.Visual == visual { +				pformat = pv.Format +			} +		} +	} + +	// ...or just scan through pformats.Formats and look for matches, which is +	// what XRenderFindStandardFormat in Xlib does as well as exp/shiny. + +	pid, err := render.NewPictureId(X) +	if err != nil { +		log.Fatalln(err) +	} +	render.CreatePicture(X, pid, xproto.Drawable(wid), pformat, 0, []uint32{}) + +	// Reserve an ID for the gradient. +	gid, err := render.NewPictureId(X) +	if err != nil { +		log.Fatalln(err) +	} + +	var from, to render.Color +	recolor := func() { +		start := rand.Uint32() & 0xffffff +		from = render.Color{ +			Red:   0x101 * uint16((start>>16)&0xff), +			Green: 0x101 * uint16((start>>8)&0xff), +			Blue:  0x101 * uint16(start&0xff), +			Alpha: 0xffff, +		} + +		end := rand.Uint32() & 0xffffff +		to = render.Color{ +			Red:   0x101 * uint16((end>>16)&0xff), +			Green: 0x101 * uint16((end>>8)&0xff), +			Blue:  0x101 * uint16(end&0xff), +			Alpha: 0xffff, +		} +	} + +	var w, h uint16 +	gradient := func() { +		if w < 100 || h < 100 { +			return +		} + +		_ = render.CreateLinearGradient(X, gid, +			render.Pointfix{F64ToFixed(0), F64ToFixed(0)}, +			render.Pointfix{F64ToFixed(0), F64ToFixed(float64(h) - 100)}, +			2, []render.Fixed{F64ToFixed(0), F64ToFixed(1)}, +			[]render.Color{from, to}) + +		_ = render.Composite(X, render.PictOpSrc, gid, render.PictureNone, pid, +			0, 0, 0, 0, 50, 50, w-100, h-100) + +		_ = render.FreePicture(X, gid) +	} + +	for { +		ev, xerr := X.WaitForEvent() +		if xerr != nil { +			log.Printf("Error: %s\n", xerr) +			return +		} +		if ev == nil { +			return +		} + +		log.Printf("Event: %s\n", ev) +		switch e := ev.(type) { +		case xproto.UnmapNotifyEvent: +			return + +		case xproto.ConfigureNotifyEvent: +			w, h = e.Width, e.Height +			recolor() + +		case xproto.KeyPressEvent: +			recolor() +			gradient() + +		case xproto.ExposeEvent: +			gradient() +		} +	} + +} | 
