Beispiel #1
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
}
Beispiel #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 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
}
Beispiel #3
0
// NewCycle creates a new prompt. As many prompts as you want can be created,
// and they could even technically be shown simultaneously so long as at most
// one of them is using a grab. (The grab will fail for the others and they
// will not be shown.)
//
// CycleTheme and CycleConfig values can either use DefaultCycle{Theme,Config}
// values found in this package, or custom ones can be created using
// composite literals.
func NewCycle(X *xgbutil.XUtil, theme *CycleTheme, config CycleConfig) *Cycle {
	cycle := &Cycle{
		X:        X,
		theme:    theme,
		config:   config,
		showing:  false,
		selected: -1,
		grabMods: 0,
	}

	// Create all windows used for the base of the cycle prompt.
	// This obviously doesn't include the windows representing the items.
	cwin := func(p xproto.Window) *xwindow.Window {
		return xwindow.Must(xwindow.Create(X, p))
	}
	cycle.win = cwin(X.RootWin())
	cycle.bTop, cycle.bBot = cwin(cycle.win.Id), cwin(cycle.win.Id)
	cycle.bLft, cycle.bRht = cwin(cycle.win.Id), cwin(cycle.win.Id)

	// Make the top-level window override redirect so the window manager
	// doesn't mess with us.
	cycle.win.Change(xproto.CwOverrideRedirect, 1)

	// Set the colors of each window.
	cclr := func(w *xwindow.Window, clr render.Color) {
		w.Change(xproto.CwBackPixel, uint32(clr.Int()))
	}
	cclr(cycle.win, cycle.theme.BgColor)
	cclr(cycle.bTop, cycle.theme.BorderColor)
	cclr(cycle.bBot, cycle.theme.BorderColor)
	cclr(cycle.bLft, cycle.theme.BorderColor)
	cclr(cycle.bRht, cycle.theme.BorderColor)

	// Map the sub-windows once. (Real mapping only happens when
	// cycle.win is mapped.)
	cycle.bTop.Map()
	cycle.bBot.Map()
	cycle.bLft.Map()
	cycle.bRht.Map()

	// Connect the key response handler (i.e., the alt-tab'ing, canceling, etc.)
	cycle.keyResponse().Connect(X, X.Dummy())

	// Guess the maximum font height.
	_, cycle.fontHeight = xgraphics.TextMaxExtents(
		cycle.theme.Font, cycle.theme.FontSize, "A")
	cycle.fontHeight += misc.TextBreathe

	return cycle
}
Beispiel #4
0
func (f *Full) UpdateTitle() {
	if f == nil {
		return
	}

	title := f.client.Name()
	font := f.theme.Font
	fontSize := f.theme.FontSize
	aFontColor := f.theme.AFontColor.ImageColor()
	iFontColor := f.theme.IFontColor.ImageColor()

	ew, eh := xgraphics.TextMaxExtents(font, fontSize, title)
	eh += misc.TextBreathe

	imgA := render.NewBorder(f.X, 0, render.NoColor, f.theme.ATitleColor,
		ew, f.theme.TitleSize,
		render.GradientVert, render.GradientRegular)
	imgI := render.NewBorder(f.X, 0, render.NoColor, f.theme.ITitleColor,
		ew, f.theme.TitleSize,
		render.GradientVert, render.GradientRegular)

	y := (f.theme.TitleSize-eh)/2 - 1

	x2, _, err := imgA.Text(0, y, aFontColor, fontSize, font, title)
	if err != nil {
		logger.Warning.Printf("Could not draw window title for window %s "+
			"because: %v", f.client, err)
	}

	_, _, err = imgI.Text(0, y, iFontColor, fontSize, font, title)
	if err != nil {
		logger.Warning.Printf("Could not draw window title for window %s "+
			"because: %v", f.client, err)
	}

	f.titleText.Create(
		imgA.SubImage(image.Rect(0, 0, x2, imgA.Bounds().Max.Y)),
		imgI.SubImage(image.Rect(0, 0, x2, imgI.Bounds().Max.Y)))

	f.titleText.MROpt(fW, 0, 0, x2, 0)
	if f.client.State() == Active {
		f.titleText.Active()
	} else {
		f.titleText.Inactive()
	}
}