stone/backends/x/x.go

152 lines
3.4 KiB
Go
Raw Normal View History

2022-11-09 13:52:49 -07:00
package x
2022-11-12 17:02:24 -07:00
// import "fmt"
import "sync"
2022-11-09 13:52:49 -07:00
import "image"
2022-11-10 10:38:02 -07:00
import "golang.org/x/image/font"
2022-11-09 13:52:49 -07:00
2022-11-12 17:02:24 -07:00
// import "github.com/jezek/xgb"
2022-11-09 13:52:49 -07:00
import "github.com/jezek/xgbutil"
2022-11-10 00:02:08 -07:00
import "github.com/jezek/xgbutil/ewmh"
2022-11-09 13:52:49 -07:00
import "github.com/jezek/xgbutil/xwindow"
import "github.com/jezek/xgbutil/xgraphics"
import "git.tebibyte.media/sashakoshka/stone"
type Backend struct {
2022-11-15 22:29:23 -07:00
application *stone.Application
config *stone.Config
callbackManager *stone.CallbackManager
connection *xgbutil.XUtil
window *xwindow.Window
canvas *xgraphics.Image
2022-11-09 13:52:49 -07:00
drawCellBounds bool
drawBufferBounds bool
2022-11-15 22:29:23 -07:00
lock sync.Mutex
2022-11-10 10:38:02 -07:00
font struct {
face font.Face
}
2022-11-10 18:43:27 -07:00
2022-11-15 09:16:29 -07:00
colors [8]xgraphics.BGRA
2022-11-09 16:53:14 -07:00
metrics struct {
2022-11-09 20:33:18 -07:00
windowWidth int
windowHeight int
cellWidth int
cellHeight int
padding int
paddingX int
paddingY int
descent int
2022-11-09 16:53:14 -07:00
}
modifierMasks struct {
capsLock uint16
shiftLock uint16
numLock uint16
modeSwitch uint16
alt uint16
meta uint16
super uint16
hyper uint16
}
windowBoundsClean bool
2022-11-09 13:52:49 -07:00
}
2022-11-10 00:02:08 -07:00
func (backend *Backend) SetTitle (title string) (err error) {
err = ewmh.WmNameSet(backend.connection, backend.window.Id, title)
return
2022-11-09 13:52:49 -07:00
}
2022-11-10 00:02:08 -07:00
func (backend *Backend) SetIcon (icons []image.Image) (err error) {
wmIcons := []ewmh.WmIcon { }
2022-11-09 13:52:49 -07:00
2022-11-10 00:02:08 -07:00
for _, icon := range icons {
width := icon.Bounds().Max.X
height := icon.Bounds().Max.Y
wmIcon := ewmh.WmIcon {
Width: uint(width),
Height: uint(height),
Data: make ([]uint, width * height),
}
// manually convert image data beacuse of course we have to do
// this
index := 0
for y := 0; y < height; y ++ {
for x := 0; x < width; x ++ {
r, g, b, a := icon.At(x, y).RGBA()
r >>= 8
g >>= 8
b >>= 8
a >>= 8
wmIcon.Data[index] =
(uint(a) << 24) |
(uint(r) << 16) |
(uint(g) << 8) |
(uint(b) << 0)
index ++
}}
wmIcons = append(wmIcons, wmIcon)
}
err = ewmh.WmIconSet(backend.connection, backend.window.Id, wmIcons)
return
2022-11-09 13:52:49 -07:00
}
2022-11-09 16:53:14 -07:00
// calculateWindowSize calculates window bounds based on the internal buffer
// size.
func (backend *Backend) calculateWindowSize () (x, y int) {
width, height := backend.application.Size()
x =
width * backend.metrics.cellWidth +
backend.metrics.padding * 2
y =
height * backend.metrics.cellHeight +
backend.metrics.padding * 2
return
}
func (backend *Backend) calculateBufferSize () (width, height int) {
width =
(backend.metrics.windowWidth - backend.metrics.padding * 2) /
backend.metrics.cellWidth
height =
(backend.metrics.windowHeight - backend.metrics.padding * 2) /
backend.metrics.cellHeight
return
}
2022-11-12 20:43:36 -07:00
func (backend *Backend) cellAt (onScreen image.Point) (x, y int) {
x = (onScreen.X - backend.metrics.paddingX) / backend.metrics.cellWidth
y = (onScreen.Y - backend.metrics.paddingY) / backend.metrics.cellHeight
return
}
2022-11-10 19:32:02 -07:00
func (backend *Backend) cellSubImage (x, y int) (cell *xgraphics.Image) {
cell = backend.canvas.SubImage(backend.boundsOfCell(x, y)).(*xgraphics.Image)
return
}
func (backend *Backend) originOfCell (x, y int) (origin image.Point) {
origin = image.Point {
X: x * backend.metrics.cellWidth + backend.metrics.paddingX,
Y: y * backend.metrics.cellHeight + backend.metrics.paddingY,
}
return
}
func (backend *Backend) boundsOfCell (x, y int) (bounds image.Rectangle) {
bounds = image.Rectangle {
Min: backend.originOfCell(x, y),
Max: backend.originOfCell(x + 1, y + 1),
}
return
2022-11-10 10:38:02 -07:00
}