Example #1
0
func (ct *CommandTray) Init() {
	var err error

	ct.img = xgraphics.New(ct.X, image.Rect(0, 0, ct.Width, ct.Height))
	ct.pu_img = xgraphics.New(ct.X, image.Rect(0, 0, ct.Width, ct.Height*10))

	ct.window, err = xwindow.Create(ct.X, ct.Parent.Id)
	utils.FailMeMaybe(err)

	utils.FailMeMaybe(ct.img.XSurfaceSet(ct.window.Id))

	ct.window.Move(ct.Position, 0)
	ct.window.Resize(ct.Width, ct.Height)
	ct.window.Map()
}
Example #2
0
// DrawText is a convenience function that will create a new image, render
// the provided text to it, paint the image to the provided window, and resize
// the window to fit the text snugly.
//
// An error can occur when rendering the text to an image.
func DrawText(win *xwindow.Window, font *truetype.Font, size float64,
	fontClr, bgClr render.Color, text string) error {

	// BUG(burntsushi): If `text` is zero-length, very bad things happen.
	if len(text) == 0 {
		text = " "
	}

	// Over estimate the extents.
	ew, eh := xgraphics.Extents(font, size, text)

	// Create an image using the over estimated extents.
	img := xgraphics.New(win.X, image.Rect(0, 0, ew, eh))
	xgraphics.BlendBgColor(img, bgClr.ImageColor())

	// Now draw the text, grab the (x, y) position advanced by the text, and
	// check for an error in rendering.
	_, _, err := img.Text(0, 0, fontClr.ImageColor(), size, font, text)
	if err != nil {
		return err
	}

	// Resize the window to the geometry determined by (x, y).
	win.Resize(ew, eh)

	// Now draw the image to the window and destroy it.
	img.XSurfaceSet(win.Id)
	// subimg := img.SubImage(image.Rect(0, 0, ew, eh))
	img.XDraw()
	img.XPaint(win.Id)
	img.Destroy()

	return nil
}
Example #3
0
// New allocates and initializes a new DockApp.  NewDockApp does not initialize
// the window contents and does not map the window to the display screen.  The
// window is mapped to the screen when the Main method is called on the
// returned DockApp.
func New(x *xgbutil.XUtil, rect image.Rectangle) (*DockApp, error) {
	win, err := xwindow.Generate(x)
	if err != nil {
		log.Fatalf("generate window: %v", err)
	}
	win.Create(x.RootWin(), 0, 0, rect.Size().X, rect.Size().Y, 0)

	// Set WM hints so that Openbox puts the window into the dock.
	hints := &icccm.Hints{
		Flags:        icccm.HintState | icccm.HintIconWindow,
		InitialState: icccm.StateWithdrawn,
		IconWindow:   win.Id,
		WindowGroup:  win.Id,
	}
	err = icccm.WmHintsSet(x, win.Id, hints)
	if err != nil {
		win.Destroy()
		return nil, fmt.Errorf("wm hints: %v", err)
	}
	img := xgraphics.New(x, rect)
	err = img.XSurfaceSet(win.Id)
	if err != nil {
		img.Destroy()
		win.Destroy()
		return nil, fmt.Errorf("xsurface set: %v", err)
	}
	app := &DockApp{
		x:   x,
		img: img,
		win: win,
	}
	return app, nil
}
Example #4
0
// DrawText is a convenience function that will create a new image, render
// the provided text to it, paint the image to the provided window, and resize
// the window to fit the text snugly.
//
// An error can occur when rendering the text to an image.
func DrawText(win *xwindow.Window, font *truetype.Font, size float64,
	fontClr, bgClr color.RGBA, text string) error {

	// Over estimate the extents.
	ew, eh := xgraphics.TextMaxExtents(font, size, text)
	eh += misc.TextBreathe // <-- this is the bug

	// Create an image using the over estimated extents.
	img := xgraphics.New(win.X, image.Rect(0, 0, ew, eh))
	xgraphics.BlendBgColor(img, bgClr)

	// Now draw the text, grab the (x, y) position advanced by the text, and
	// check for an error in rendering.
	x, y, err := img.Text(0, 0, fontClr, size, font, text)
	if err != nil {
		return err
	}

	// Resize the window to the geometry determined by (x, y).
	w, h := x, y+misc.TextBreathe // <-- also part of the bug
	win.Resize(w, h)

	// Now draw the image to the window and destroy it.
	img.XSurfaceSet(win.Id)
	subimg := img.SubImage(image.Rect(0, 0, w, h))
	subimg.XDraw()
	subimg.XPaint(win.Id)
	img.Destroy()

	return nil
}
Example #5
0
// NewInput constructs Input values. It needs an X connection, a parent window,
// the width of the input box, and theme information related for the font
// and background. Padding separating the text and the edges of the window
// may also be specified.
//
// While NewInput returns an *Input, a Input value also has an xwindow.Window
// value embedded into it. Thus, an Input can also be treated as a normal
// window on which you can assign callbacks, close, destroy, etc.
//
// As with all windows, the Input window should be destroyed when it is no
// longer in used.
func NewInput(X *xgbutil.XUtil, parent xproto.Window, width int, padding int,
	font *truetype.Font, fontSize float64,
	fontColor, bgColor render.Color) *Input {

	_, height := xgraphics.TextMaxExtents(font, fontSize, "M")
	height += misc.TextBreathe

	width, height = width+2*padding, height+2*padding

	img := xgraphics.New(X, image.Rect(0, 0, width, height))
	win := xwindow.Must(xwindow.Create(X, parent))
	win.Listen(xproto.EventMaskKeyPress)
	win.Resize(width, height)

	ti := &Input{
		Window:    win,
		img:       img,
		Text:      make([]rune, 0, 50),
		font:      font,
		fontSize:  fontSize,
		fontColor: fontColor,
		bgColor:   bgColor,
		padding:   padding,
	}

	ti.Render()
	return ti
}
Example #6
0
// NewImage returns a new image canvas
// that draws to the given image.  The
// minimum point of the given image
// should probably be 0,0.
func NewImage(img draw.Image, name string) (*Canvas, error) {
	w := float64(img.Bounds().Max.X - img.Bounds().Min.X)
	h := float64(img.Bounds().Max.Y - img.Bounds().Min.Y)

	X, err := xgbutil.NewConn()
	if err != nil {
		return nil, err
	}
	keybind.Initialize(X)
	ximg := xgraphics.New(X, image.Rect(0, 0, int(w), int(h)))
	err = ximg.CreatePixmap()
	if err != nil {
		return nil, err
	}
	painter := NewPainter(ximg)
	gc := draw2d.NewGraphicContextWithPainter(ximg, painter)
	gc.SetDPI(dpi)
	gc.Scale(1, -1)
	gc.Translate(0, -h)

	wid := ximg.XShowExtra(name, true)
	go func() {
		xevent.Main(X)
	}()

	c := &Canvas{
		Canvas: vgimg.NewWith(vgimg.UseImageWithContext(img, gc)),
		x:      X,
		ximg:   ximg,
		wid:    wid,
	}
	vg.Initialize(c)
	return c, nil
}
Example #7
0
func NewDisplay(width, height, border, heading int, name string) (*Display, error) {
	d := new(Display)
	d.w = float64(width)
	d.h = float64(height)
	d.bord = float64(border)
	d.head = float64(heading)
	X, err := xgbutil.NewConn()
	if err != nil {
		return nil, err
	}
	keybind.Initialize(X)
	d.ximg = xgraphics.New(X, image.Rect(
		0,
		0,
		border*2+width,
		border*2+heading+height))
	err = d.ximg.CreatePixmap()
	if err != nil {
		return nil, err
	}
	painter := NewXimgPainter(d.ximg)
	d.gc = draw2d.NewGraphicContextWithPainter(d.ximg, painter)
	d.gc.Save()
	d.gc.SetStrokeColor(color.White)
	d.gc.SetFillColor(color.White)
	d.gc.Clear()
	d.wid = d.ximg.XShowExtra(name, true)
	d.x = X
	go func() {
		xevent.Main(X)
	}()
	return d, nil
}
Example #8
0
func main() {
	X, err := xgbutil.NewConn()
	if err != nil {
		log.Fatal(err)
	}

	// Load some font. You may need to change the path depending upon your
	// system configuration.
	fontReader, err := os.Open(fontPath)
	if err != nil {
		log.Fatal(err)
	}

	// Now parse the font.
	font, err := xgraphics.ParseFont(fontReader)
	if err != nil {
		log.Fatal(err)
	}

	// Create some canvas.
	ximg := xgraphics.New(X, image.Rect(0, 0, canvasWidth, canvasHeight))
	ximg.For(func(x, y int) xgraphics.BGRA {
		return bg
	})

	// Now write the text.
	_, _, err = ximg.Text(10, 10, fg, size, font, msg)
	if err != nil {
		log.Fatal(err)
	}

	// Compute extents of first line of text.
	_, firsth := xgraphics.Extents(font, size, msg)

	// Now show the image in its own window.
	win := ximg.XShowExtra("Drawing text using xgraphics", true)

	// Now draw some more text below the above and demonstrate how to update
	// only the region we've updated.
	_, _, err = ximg.Text(10, 10+firsth, fg, size, font, "Some more text.")
	if err != nil {
		log.Fatal(err)
	}

	// Now compute extents of the second line of text, so we know which region
	// to update.
	secw, sech := xgraphics.Extents(font, size, "Some more text.")

	// Now repaint on the region that we drew text on. Then update the screen.
	bounds := image.Rect(10, 10+firsth, 10+secw, 10+firsth+sech)
	ximg.SubImage(bounds).XDraw()
	ximg.XPaint(win.Id)

	// All we really need to do is block, which could be achieved using
	// 'select{}'. Invoking the main event loop however, will emit error
	// message if anything went seriously wrong above.
	xevent.Main(X)
}
Example #9
0
func NewSolid(X *xgbutil.XUtil, bgColor Color, width, height int) *Image {
	img := New(xgraphics.New(X, image.Rect(0, 0, width, height)))

	r, g, b := bgColor.RGB8()
	img.ForExp(func(x, y int) (uint8, uint8, uint8, uint8) {
		return r, g, b, 0xff
	})
	return img
}
Example #10
0
func NewGUI(board *Board) *GUI {
	gui := new(GUI)
	X, _ := xgbutil.NewConn()
	gui.canvas = xgraphics.New(X, image.Rect(0, 0, board.Width(), board.Height()))
	gui.queue = make(map[Pos]bool, board.Width()*board.Height())
	gui.win = gui.canvas.XShow()
	gui.board = board
	board.onUpdate = func(p Pos) { gui.Update(p) }
	gui.StartLoop()
	return gui
}
Example #11
0
func NewWindow(width, height int) (w *Window, err error) {

	w = new(Window)
	w.width, w.height = width, height

	w.xu, err = xgbutil.NewConn()
	if err != nil {
		return
	}

	w.conn = w.xu.Conn()
	screen := w.xu.Screen()

	w.win, err = xwindow.Generate(w.xu)
	if err != nil {
		return
	}

	err = w.win.CreateChecked(screen.Root, 600, 500, width, height, 0)
	if err != nil {
		return
	}

	w.win.Listen(AllEventsMask)

	err = icccm.WmProtocolsSet(w.xu, w.win.Id, []string{"WM_DELETE_WINDOW"})
	if err != nil {
		fmt.Println(err)
		err = nil
	}

	w.bufferLck = &sync.Mutex{}
	w.buffer = xgraphics.New(w.xu, image.Rect(0, 0, width, height))
	w.buffer.XSurfaceSet(w.win.Id)

	keyMap, modMap := keybind.MapsGet(w.xu)
	keybind.KeyMapSet(w.xu, keyMap)
	keybind.ModMapSet(w.xu, modMap)

	w.events = make(chan interface{})

	w.SetIcon(Gordon)
	w.SetIconName("Go")

	go w.handleEvents()

	return
}
Example #12
0
// NewBackground creates an xgraphics.Image which spans the entire screen,
// initialized to black.
func NewBackground(X *xgbutil.XUtil) (*xgraphics.Image, error) {
	res, err := randr.GetScreenResources(X.Conn(), X.RootWin()).Reply()
	if err != nil {
		return nil, err
	}
	var bgRect image.Rectangle
	for _, output := range res.Outputs {
		r, err := util.OutputRect(X, output)
		// NOTE: It doesn't really matter if this returns a Zero Rectangle.
		if err != nil {
			return nil, err
		}
		bgRect = bgRect.Union(r)
	}
	return xgraphics.New(X, bgRect), nil
}
Example #13
0
func (c *Clock) Init() {
	var err error
	c.img = xgraphics.New(c.X, image.Rect(0, 0, c.Width, c.Height))
	c.window, err = xwindow.Create(c.X, c.Parent.Id)
	utils.FailMeMaybe(err)

	c.window.Resize(c.Width, c.Height)
	c.window.Move(c.Position, 0)
	c.img.XSurfaceSet(c.window.Id)

	c.window.Map()

	c.Draw()

	go c.tickTock()
}
Example #14
0
func main() {
	runtime.GOMAXPROCS(64)

	X, err := xgbutil.NewConn()
	if err != nil {
		log.Fatal(err)
	}

	keybind.Initialize(X)

	font := loadFont("/usr/share/fonts/truetype/freefont/FreeMono.ttf")
	font.Color = xgraphics.BGRA{B: 0x00, G: 0xff, R: 0x00, A: 0xff}
	font.Size = 12.0

	ximage := xgraphics.New(X, image.Rect(0, 0, 300, 300))
	ximage.CreatePixmap()
	window, obscured := makeWindow(ximage)

	battery := batteryItem(font, 10, ximage, window)
	cpu := cpuItem(font, 30, ximage, window)
	memory := memoryItem(font, 50, ximage, window)
	before, after, quit := xevent.MainPing(X)
loop:
	for {
		select {
		case <-before:
			<-after
		case <-quit:
			break loop
		case text := <-battery.Text:
			if *obscured {
				continue loop
			}
			battery.update(text)
		case text := <-cpu.Text:
			if *obscured {
				continue loop
			}
			cpu.update(text)
		case text := <-memory.Text:
			if *obscured {
				continue loop
			}
			memory.update(text)
		}
	}
}
Example #15
0
func (sb *StatusBar) Init() {
	sb.img = xgraphics.New(sb.X, image.Rect(0, 0, sb.Width, sb.Height))
	var err error

	sb.window, err = xwindow.Create(sb.X, sb.Parent.Id)
	utils.FailMeMaybe(err)

	sb.window.Move(sb.Position, 0)
	sb.window.Resize(sb.Width, sb.Height)
	sb.window.Map()

	sb.img.XSurfaceSet(sb.window.Id)

	utils.FailMeMaybe(sb.initTray())

	sb.Draw()
}
Example #16
0
func NewBorder(X *xgbutil.XUtil, borderType int, borderColor,
	bgColor Color, width, height, gradientType, gradientDir int) *Image {

	img := New(xgraphics.New(X, image.Rect(0, 0, width, height)))

	// bgClr could be a gradient!
	if bgColor.IsGradient() {
		img.Gradient(gradientType, gradientDir, bgColor)
	} else {
		r, g, b := bgColor.RGB8()
		img.ForExp(func(x, y int) (uint8, uint8, uint8, uint8) {
			return r, g, b, 0xff
		})
	}

	img.ThinBorder(borderType, borderColor)
	return img
}
Example #17
0
func NewCorner(X *xgbutil.XUtil, borderType int, borderColor,
	bgColor Color, width, height, diagonal int) *Image {

	// If bgColor isn't a gradient, then we can cheat
	if !bgColor.IsGradient() {
		return NewBorder(X, borderType, borderColor, bgColor,
			width, height, 0, 0)
	}

	img := New(xgraphics.New(X, image.Rect(0, 0, width, height)))

	// aliases for convenience
	vert, horz := GradientVert, GradientHorz
	reg, rev := GradientRegular, GradientReverse

	// for Top Left to Bottom Right diagonals
	belowTLDiag := func(x, y int) bool { return y > x }
	aboveTLDiag := func(x, y int) bool { return y <= x }

	// for Bottom Left to Top Right diagonals
	belowBLDiag := func(x, y int) bool { return y > (width - x) }
	aboveBLDiag := func(x, y int) bool { return y <= (width - x) }

	switch diagonal {
	case DiagBottomLeft:
		img.GradientFunc(horz, reg, bgColor, aboveBLDiag)
		img.GradientFunc(vert, rev, bgColor, belowBLDiag)
	case DiagTopRight:
		img.GradientFunc(vert, reg, bgColor, aboveBLDiag)
		img.GradientFunc(horz, rev, bgColor, belowBLDiag)
	case DiagBottomRight:
		img.GradientFunc(horz, rev, bgColor, aboveTLDiag)
		img.GradientFunc(vert, rev, bgColor, belowTLDiag)
	default: // DiagTopLeft:
		img.GradientFunc(vert, reg, bgColor, aboveTLDiag)
		img.GradientFunc(horz, reg, bgColor, belowTLDiag)
	}

	img.ThinBorder(borderType, borderColor)
	return img
}
Example #18
0
// NewImage returns a new image canvas
// that draws to the given image.  The
// minimum point of the given image
// should probably be 0,0.
func NewImage(img draw.Image, name string) (*XImgCanvas, error) {
	w := float64(img.Bounds().Max.X - img.Bounds().Min.X)
	h := float64(img.Bounds().Max.Y - img.Bounds().Min.Y)

	X, err := xgbutil.NewConn()
	if err != nil {
		return nil, err
	}
	keybind.Initialize(X)
	ximg := xgraphics.New(X, image.Rect(0, 0, int(w), int(h)))
	err = ximg.CreatePixmap()
	if err != nil {
		return nil, err
	}
	painter := NewXimgPainter(ximg)
	gc := draw2d.NewGraphicContextWithPainter(ximg, painter)
	gc.SetDPI(dpi)
	gc.Scale(1, -1)
	gc.Translate(0, -h)

	wid := ximg.XShowExtra(name, true)
	go func() {
		xevent.Main(X)
	}()

	c := &XImgCanvas{
		gc:    gc,
		w:     vg.Inches(w / dpi),
		h:     vg.Inches(h / dpi),
		color: []color.Color{color.Black},
		x:     X,
		ximg:  ximg,
		wid:   wid,
	}
	vg.Initialize(c)
	return c, nil
}
Example #19
0
// paintGradient creates a new xgraphics.Image value and draws a gradient
// starting at color 'start' and ending at color 'end'.
//
// Since xgraphics.Image values use pixmaps and pixmaps cannot be resized,
// a new pixmap must be allocated for each resize event.
func paintGradient(X *xgbutil.XUtil, wid xproto.Window, width, height int,
	start, end color.RGBA) {

	ximg := xgraphics.New(X, image.Rect(0, 0, width, height))

	// Now calculate the increment step between each RGB channel in
	// the start and end colors.
	rinc := (0xff * (int(end.R) - int(start.R))) / width
	ginc := (0xff * (int(end.G) - int(start.G))) / width
	binc := (0xff * (int(end.B) - int(start.B))) / width

	// Now apply the increment to each "column" in the image.
	// Using 'ForExp' allows us to bypass the creation of a color.BGRA value
	// for each pixel in the image.
	ximg.ForExp(func(x, y int) (uint8, uint8, uint8, uint8) {
		return uint8(int(start.B) + (binc*x)/0xff),
			uint8(int(start.G) + (ginc*x)/0xff),
			uint8(int(start.R) + (rinc*x)/0xff),
			0xff
	})

	// Set the surface to paint on for ximg.
	// (This simply sets the background pixmap of the window to the pixmap
	// used by ximg.)
	ximg.XSurfaceSet(wid)

	// XDraw will draw the contents of ximg to its corresponding pixmap.
	ximg.XDraw()

	// XPaint will "clear" the window provided so that it shows the updated
	// pixmap.
	ximg.XPaint(wid)

	// Since we will not reuse ximg, we must destroy its pixmap.
	ximg.Destroy()
}
Example #20
0
func (t *Tracker) Init() {
	var err error
	t.img = xgraphics.New(t.X, image.Rect(0, 0, t.Size, t.Size))
	t.window, err = xwindow.Create(t.X, t.Parent.Id)
	utils.FailMeMaybe(err)

	t.window.Resize(t.Size, t.Size)
	t.window.Move(t.Position, 0)

	t.img.XSurfaceSet(t.window.Id)

	t.window.Map()

	t.stopMe = true

	l := startup.Listener{
		X:         t.X,
		Callbacks: t,
	}

	l.Initialize()

	t.Draw()
}
Example #21
0
func (w *Window) handleEvents() {
	var noX int32 = 1<<31 - 1
	noX++
	var lastX, lastY int32 = noX, 0
	var button wde.Button

	downKeys := map[string]bool{}

	for {
		e, err := w.conn.WaitForEvent()

		if err != nil {
			fmt.Println("[go.wde X error] ", err)
			continue
		}

		switch e := e.(type) {

		case xproto.ButtonPressEvent:
			button = button | buttonForDetail(e.Detail)
			var bpe wde.MouseDownEvent
			bpe.Which = buttonForDetail(e.Detail)
			bpe.Where.X = int(e.EventX)
			bpe.Where.Y = int(e.EventY)
			lastX = int32(e.EventX)
			lastY = int32(e.EventY)
			w.events <- bpe

		case xproto.ButtonReleaseEvent:
			button = button & ^buttonForDetail(e.Detail)
			var bue wde.MouseUpEvent
			bue.Which = buttonForDetail(e.Detail)
			bue.Where.X = int(e.EventX)
			bue.Where.Y = int(e.EventY)
			lastX = int32(e.EventX)
			lastY = int32(e.EventY)
			w.events <- bue

		case xproto.LeaveNotifyEvent:
			var wee wde.MouseExitedEvent
			wee.Where.X = int(e.EventX)
			wee.Where.Y = int(e.EventY)
			if lastX != noX {
				wee.From.X = int(lastX)
				wee.From.Y = int(lastY)
			} else {
				wee.From.X = wee.Where.X
				wee.From.Y = wee.Where.Y
			}
			lastX = int32(e.EventX)
			lastY = int32(e.EventY)
			w.events <- wee
		case xproto.EnterNotifyEvent:
			var wee wde.MouseEnteredEvent
			wee.Where.X = int(e.EventX)
			wee.Where.Y = int(e.EventY)
			if lastX != noX {
				wee.From.X = int(lastX)
				wee.From.Y = int(lastY)
			} else {
				wee.From.X = wee.Where.X
				wee.From.Y = wee.Where.Y
			}
			lastX = int32(e.EventX)
			lastY = int32(e.EventY)
			w.events <- wee

		case xproto.MotionNotifyEvent:
			var mme wde.MouseMovedEvent
			mme.Where.X = int(e.EventX)
			mme.Where.Y = int(e.EventY)
			if lastX != noX {
				mme.From.X = int(lastX)
				mme.From.Y = int(lastY)
			} else {
				mme.From.X = mme.Where.X
				mme.From.Y = mme.Where.Y
			}
			lastX = int32(e.EventX)
			lastY = int32(e.EventY)
			if button == 0 {
				w.events <- mme
			} else {
				var mde wde.MouseDraggedEvent
				mde.MouseMovedEvent = mme
				mde.Which = button
				w.events <- mde
			}

		case xproto.KeyPressEvent:
			var ke wde.KeyEvent
			code := keybind.LookupString(w.xu, e.State, e.Detail)
			ke.Key = keyForCode(code)
			w.events <- wde.KeyDownEvent(ke)
			downKeys[ke.Key] = true
			kpe := wde.KeyTypedEvent{
				KeyEvent: ke,
				Glyph:    letterForCode(code),
				Chord:    wde.ConstructChord(downKeys),
			}
			w.events <- kpe

		case xproto.KeyReleaseEvent:
			var ke wde.KeyUpEvent
			ke.Key = keyForCode(keybind.LookupString(w.xu, e.State, e.Detail))
			delete(downKeys, ke.Key)
			w.events <- ke

		case xproto.ConfigureNotifyEvent:
			var re wde.ResizeEvent
			re.Width = int(e.Width)
			re.Height = int(e.Height)
			if re.Width != w.width || re.Height != w.height {
				w.width, w.height = re.Width, re.Height

				w.bufferLck.Lock()
				w.buffer.Destroy()
				w.buffer = xgraphics.New(w.xu, image.Rect(0, 0, re.Width, re.Height))
				w.bufferLck.Unlock()

				w.events <- re
			}

		case xproto.ClientMessageEvent:
			if icccm.IsDeleteProtocol(w.xu, xevent.ClientMessageEvent{&e}) {
				w.events <- wde.CloseEvent{}
			}
		case xproto.DestroyNotifyEvent:
		case xproto.ReparentNotifyEvent:
		case xproto.MapNotifyEvent:
		case xproto.UnmapNotifyEvent:
		case xproto.PropertyNotifyEvent:

		default:
			fmt.Printf("unhandled event: type %T\n%+v\n", e, e)
		}

	}

	close(w.events)
}
Example #22
0
func main() {
	X, err := xgbutil.NewConn()
	if err != nil {
		log.Println(err)
		return
	}

	//Initialize the keybind package
	keybind.Initialize(X)

	//Create a window
	win, err := xwindow.Generate(X)
	if err != nil {
		log.Fatalf("Could not generate a new window X id: %s", err)
	}
	win.Create(X.RootWin(), 0, 0, 1024, 768, xproto.CwBackPixel, 0x606060ff)

	// Listen for Key{Press,Release} events.
	win.Listen(xproto.EventMaskKeyPress, xproto.EventMaskKeyRelease)

	// Map the window. This is what makes it on the screen
	win.Map()

	//Make a ...callback... for the events and connect
	xevent.KeyPressFun(
		func(X *xgbutil.XUtil, e xevent.KeyPressEvent) {
			modStr := keybind.ModifierString(e.State)
			keyStr := keybind.LookupString(X, e.State, e.Detail)
			if len(modStr) > 0 {
				log.Printf("Key: %s-%s\n", modStr, keyStr)
			} else {
				log.Println("Key:", keyStr)
			}

			if keybind.KeyMatch(X, "Escape", e.State, e.Detail) {
				if e.State&xproto.ModMaskControl > 0 {
					log.Println("Control-Escape detected. Quitting...")
					xevent.Quit(X)
				}
			}
		}).Connect(X, win.Id)

	//So here i'm going to try to make a image..'
	img := xgraphics.New(X, image.Rect(0, 0, 1024, 768))

	err = img.XSurfaceSet(win.Id)
	if err != nil {
		log.Printf("Error while setting window surface to image %d: %s\n",
			win, err)
	} else {
		log.Printf("Window %d surface set to image OK\n", win)
	}

	// I /think/ XDraw actually sends data to server?
	img.XDraw()
	// I /think/ XPaint tells the server to paint image to window
	img.XPaint(win.Id)

	//Start the routine that updates the window
	go updater(img, win)

	//This seems to start a main loop for listening to xevents
	xevent.Main(X)
}
Example #23
0
func main() {
	// Signal Handling.

	sigChan := make(chan os.Signal)

	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)

	paths := basedir.Paths{
		XDGSuffix:    "gobar",
		GoImportPath: "github.com/AmandaCameron/gobar/data",
	}

	file, err := paths.ConfigFile("config.wini")
	utils.FailMeMaybe(err)

	cfg := loadConfig(file) //os.Getenv("HOME") + "/.config/gobar/config.wini")

	// Load Images.

	images.Init(paths)

	// Setup the X Connection

	X, err := xgbutil.NewConn()
	utils.FailMeMaybe(err)

	win, err := xwindow.Create(X, X.RootWin())
	utils.FailMeMaybe(err)

	win.Resize(cfg.BarWidth, cfg.BarSize)

	// Setup the EWMH Stuff

	utils.FailMeMaybe(ewmh.RestackWindow(X, win.Id))

	var strut *ewmh.WmStrutPartial

	if cfg.Position == "Top" {
		strut = &ewmh.WmStrutPartial{
			Top:       uint(cfg.BarSize),
			TopStartX: 0,
			TopEndX:   uint(cfg.BarWidth),
		}

		win.Move(0, 0)
	} else if cfg.Position == "Bottom" {
		strut = &ewmh.WmStrutPartial{
			Bottom:       uint(cfg.BarSize),
			BottomStartX: 0,
			BottomEndX:   uint(cfg.BarWidth),
		}

		win.Move(0, 600-cfg.BarSize)
	} else {
		println("Invalid Position:", cfg.Position)
		os.Exit(1)
	}

	utils.FailMeMaybe(ewmh.WmStrutPartialSet(X, win.Id, strut))

	utils.FailMeMaybe(ewmh.WmWindowTypeSet(X, win.Id, []string{
		"_NET_WM_WINDOW_TYPE_DOCK",
	}))

	// Put us everywhere.
	utils.FailMeMaybe(ewmh.WmDesktopSet(X, win.Id, 0xFFFFFFFF))

	win.Map()

	keybind.Initialize(X)

	// Get the DE settings, if we can.

	xs, err := xsettings.New(X)
	if err != nil {
		// Maybe this should be an error, maybe not?
		xs = nil
	}

	// Draw the background

	bg := xgraphics.BGRA{
		R: 64,
		G: 64,
		B: 64,
		A: 255,
	}

	img := xgraphics.New(X, image.Rect(0, 0, cfg.BarWidth, cfg.BarSize))

	img.For(func(x, y int) xgraphics.BGRA {
		return bg
	})

	utils.FailMeMaybe(img.XSurfaceSet(win.Id))
	img.XDraw()
	img.XPaint(win.Id)

	// Connect to DBus

	sys, err := dbus.Connect(dbus.SystemBus)
	utils.FailMeMaybe(err)

	// The session bus, too.

	sess, err := dbus.Connect(dbus.SessionBus)
	utils.FailMeMaybe(err)

	// Blah

	x := xdg.New()

	// TODO: How should this fail? I imagine defaulting to gnome is the wrong thing to do,
	// but I'm not really sure what it should do.
	if xs != nil {
		theme, err := xs.GetString("Net/IconThemeName")
		if err == nil {
			x.SetTheme(theme)
		}
	}

	var dev *nm.Device
	var batt *upower.Device

	up := upower.New(sys)
	cli := nm.New(sys)

	if devs, err := cli.GetDevices(); err == nil {
		for _, d := range devs {
			if d.Type() == nm.Wireless {
				dev = d

				break
			}
		}
	}

	if pdevs, err := up.GetDevices(); err == nil {
		for _, d := range pdevs {
			if d.Type() == upower.Battery {
				batt = d
				break
			}
		}
	}

	// Clock

	clck := &Clock{
		X:          X,
		Position:   cfg.Clock.Position,
		Width:      cfg.Clock.Width,
		Height:     cfg.BarSize,
		Parent:     win,
		Format:     cfg.ClockFormat,
		Background: xgraphics.BGRA{R: 48, G: 48, B: 48, A: 255},
		Foreground: xgraphics.BGRA{R: 255, G: 255, B: 255, A: 255},
		Font:       utils.OpenFont(cfg.Clock.Font.Name),
		FontSize:   cfg.Clock.Font.Size,
	}

	clck.Init()

	// App Launch Tracker

	tracker := &Tracker{
		X:          X,
		Position:   cfg.Tracker.Position,
		Size:       cfg.BarSize,
		Background: bg,
		Parent:     win,
	}

	tracker.Init()

	// Command Tray

	ct := &commandtray.CommandTray{
		X:        X,
		Width:    cfg.Command.Width,
		Height:   cfg.BarSize,
		Position: cfg.Command.Position,
		Parent:   win,
		Font:     utils.OpenFont(cfg.Command.Font.Name),
		FontSize: cfg.Command.Font.Size,
	}

	commandtray.Register(commandtray.AppSource{
		Xdg:        x,
		X:          X,
		AppTracker: tracker,
	})

	if sess != nil {
		commandtray.Register(commandtray.GnomeSessionSource{
			Obj: sess.Object("org.gnome.SessionManager", "/org/gnome/SessionManager"),
			Xdg: x,
		})

		commandtray.Register(commandtray.NewShellSource(sess, x))

		commandtray.Register(&commandtray.AppMenuSource{
			Conn: sess,
		})
	}

	// Done, maybe?

	ct.Init()
	ct.Bind(cfg.CommandAccel)
	ct.Draw()

	// Status Bar

	sb := &statbar.StatusBar{
		X:        X,
		Width:    cfg.StatusBar.Width,
		Position: cfg.StatusBar.Position,
		Height:   cfg.BarSize,
		Parent:   win,
	}

	sb.Init()

	if batt != nil {
		sb.Add(&statbar.SbPower{batt})
	}

	if dev != nil {
		sb.Add(&statbar.SbNmWifi{dev})
		commandtray.Register(commandtray.NmSource{dev})
	}

	sb.Draw()

	// My My this anikin guy...

	go func() {
		for {
			select {
			case <-sigChan:
				sb.Teardown()

				time.Sleep(1 * time.Second)
				// Anybody else?
				xevent.Quit(X)
			}
		}
	}()

	xevent.Main(X)
}
Example #24
0
func main() {
	X, err := xgbutil.NewConn()
	fatal(err)

	// Whenever the mousebind package is used, you must call Initialize.
	// Similarly for the keybind package.
	keybind.Initialize(X)
	mousebind.Initialize(X)

	// Easter egg! Use a right click to draw a gopher.
	gopherPng, _, err := image.Decode(bytes.NewBuffer(gopher.GopherPng()))
	fatal(err)

	// Now scale it to a reasonable size.
	gopher := xgraphics.Scale(gopherPng, gopherWidth, gopherHeight)

	// Create a new xgraphics.Image. It automatically creates an X pixmap for
	// you, and handles drawing to windows in the XDraw, XPaint and
	// XSurfaceSet functions.
	// N.B. An error is possible since X pixmap allocation can fail.
	canvas := xgraphics.New(X, image.Rect(0, 0, width, height))

	// Color in the background color.
	canvas.For(func(x, y int) xgraphics.BGRA {
		return bg
	})

	// Use the convenience function XShowExtra to create and map the
	// canvas window.
	// XShowExtra will also set the surface window of canvas for us.
	// We also use XShowExtra to set the name of the window and to quit the
	// main event loop when the window is closed.
	win := canvas.XShowExtra("Pointer painting", true)

	// Listen for pointer motion events and key press events.
	win.Listen(xproto.EventMaskButtonPress | xproto.EventMaskButtonRelease |
		xproto.EventMaskKeyPress)

	// The mousebind drag function runs three callbacks: one when the drag is
	// first started, another at each "step" in the drag, and a final one when
	// the drag is done.
	// The button sequence (in this case '1') is pressed, the first callback
	// is executed. If the first return value is true, the drag continues
	// and a pointer grab is initiated with the cursor id specified in the
	// second return value (use 0 to keep the cursor unchanged).
	// If it's false, the drag stops.
	// Note that Drag will automatically compress MotionNotify events.
	mousebind.Drag(X, win.Id, win.Id, "1", false,
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) (bool, xproto.Cursor) {
			drawPencil(canvas, win, ex, ey)
			return true, 0
		},
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) {
			drawPencil(canvas, win, ex, ey)
		},
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) {})

	mousebind.Drag(X, win.Id, win.Id, "3", false,
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) (bool, xproto.Cursor) {
			drawGopher(canvas, gopher, win, ex, ey)
			return true, 0
		},
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) {
			drawGopher(canvas, gopher, win, ex, ey)
		},
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) {})

	// Bind to the clear key specified, and just redraw the bg color.
	keybind.KeyPressFun(
		func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) {
			clearCanvas(canvas, win)
		}).Connect(X, win.Id, clearKey, false)

	// Bind a callback to each key specified in the 'pencils' color map.
	// The response is to simply switch the pencil color.
	for key, clr := range pencils {
		c := clr
		keybind.KeyPressFun(
			func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) {
				log.Printf("Changing pencil color to: %#v", c)
				pencil = c
			}).Connect(X, win.Id, key, false)
	}

	// Output some basic directions.
	fmt.Println("Use the left or right buttons on your mouse to paint " +
		"squares and gophers.")
	fmt.Println("Pressing numbers 1, 2, 3, 4, 5 or 6 will switch your pencil " +
		"color.")
	fmt.Println("Pressing 'c' will clear the canvas.")

	xevent.Main(X)
}