From 1fdf14f351f274a5d6690985c854e12ab6e05fbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Sat, 18 Aug 2018 01:18:24 +0200 Subject: [PATCH] xgb-window: add a basic xgb demo Demonstrating RGBA visuals and direct pixel values. --- prototypes/xgb-window.go | 133 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 prototypes/xgb-window.go diff --git a/prototypes/xgb-window.go b/prototypes/xgb-window.go new file mode 100644 index 0000000..2519fe9 --- /dev/null +++ b/prototypes/xgb-window.go @@ -0,0 +1,133 @@ +package main + +import ( + "github.com/BurntSushi/xgb" + "github.com/BurntSushi/xgb/xproto" + "log" + "math/rand" +) + +func main() { + X, err := xgb.NewConn() + if 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 := "Gradient" + _ = xproto.ChangeProperty(X, xproto.PropModeReplace, wid, xproto.AtomWmName, + xproto.AtomString, 8, uint32(len(title)), []byte(title)) + + _ = xproto.MapWindow(X, wid) + + cid, err := xproto.NewGcontextId(X) + if err != nil { + log.Fatalln(err) + } + + _ = xproto.CreateGC(X, cid, xproto.Drawable(wid), + xproto.GcGraphicsExposures, []uint32{0}) + + var w, h uint16 + var start, end uint32 = 0xabcdef, 0x32ab54 + gradient := func() { + ra, ga, ba := (start>>16)&0xff, (start>>8)&0xff, start&0xff + rb, gb, bb := (end>>16)&0xff, (end>>8)&0xff, end&0xff + + var low, high uint16 = 50, h - 50 + if high > h { + return + } + + for y := low; y < high; y++ { + ratio := float64(y-low) / (float64(high) - float64(low)) + iratio := 1 - ratio + + rR := uint32(ratio*float64(ra)+iratio*float64(rb)) & 0xff + gG := uint32(ratio*float64(ga)+iratio*float64(gb)) & 0xff + bB := uint32(ratio*float64(ba)+iratio*float64(bb)) & 0xff + + _ = xproto.ChangeGC(X, cid, xproto.GcForeground, + []uint32{0xff000000 | rR<<16 | gG<<8 | bB}) + _ = xproto.PolyLine(X, xproto.CoordModeOrigin, xproto.Drawable(wid), + cid, []xproto.Point{ + {X: 50, Y: int16(y)}, + {X: int16(w - 50), Y: int16(y)}, + }) + } + } + + 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 + + case xproto.KeyPressEvent: + start = rand.Uint32() & 0xffffff + end = rand.Uint32() & 0xffffff + gradient() + + case xproto.ExposeEvent: + gradient() + } + } + +}