X backend better handles expose events

Previously, when an expose event was recieved, the backend would
call Window.paste, converting RGBA image data to BGRA image data.
Now we only call Window.pushRegion with the bounds given to us by
the expose event(s). This speeds up window resizing significantly.
This commit is contained in:
Sasha Koshka 2023-03-07 12:48:29 -05:00
parent 803812f9c9
commit 423e6869c0
4 changed files with 29 additions and 11 deletions

View File

@ -24,22 +24,27 @@ func (pattern Texture) Draw (destination canvas.Canvas, clip image.Rectangle) {
srcPoint := bounds.Min.Sub(realBounds.Min).Add(srcBounds.Min)
srcPoint.X = wrap(srcPoint.X, srcBounds.Min.X, srcBounds.Max.X)
srcPoint.Y = wrap(srcPoint.Y, srcBounds.Min.Y, srcBounds.Max.Y)
srcPointXStart := srcPoint.X
for dstPoint.Y = bounds.Min.Y; dstPoint.Y < bounds.Max.Y; dstPoint.Y ++ {
srcPoint.X = srcPointXStart
srcPoint.X = srcBounds.Min.X
dstPoint.X = bounds.Min.X
dstYComponent := dstPoint.Y * dstStride
srcYComponent := srcPoint.Y * srcStride
for dstPoint.X = bounds.Min.X; dstPoint.X < bounds.Max.X; dstPoint.X ++ {
dstIndex := dstPoint.X + dstPoint.Y * dstStride
srcIndex :=
srcPoint.X +
srcPoint.Y * srcStride
for {
dstIndex := dstYComponent + dstPoint.X
srcIndex := srcYComponent + srcPoint.X
dstData[dstIndex] = srcData[srcIndex]
srcPoint.X ++
if srcPoint.X >= srcBounds.Max.X {
srcPoint.X = srcBounds.Min.X
}
dstPoint.X ++
if dstPoint.X >= bounds.Max.X {
break
}
}
srcPoint.Y ++

View File

@ -1,5 +1,6 @@
package x
import "image"
import "git.tebibyte.media/sashakoshka/tomo/input"
import "git.tebibyte.media/sashakoshka/tomo/elements"
@ -47,8 +48,8 @@ func (window *Window) handleExpose (
connection *xgbutil.XUtil,
event xevent.ExposeEvent,
) {
_ = window.compressExpose(*event.ExposeEvent)
window.redrawChildEntirely()
_, region := window.compressExpose(*event.ExposeEvent)
window.pushRegion(region)
}
func (window *Window) handleConfigureNotify (
@ -234,7 +235,13 @@ func (window *Window) compressExpose (
firstEvent xproto.ExposeEvent,
) (
lastEvent xproto.ExposeEvent,
region image.Rectangle,
) {
region = image.Rect (
int(firstEvent.X), int(firstEvent.Y),
int(firstEvent.X + firstEvent.Width),
int(firstEvent.Y + firstEvent.Height))
window.backend.connection.Sync()
xevent.Read(window.backend.connection, false)
lastEvent = firstEvent
@ -245,8 +252,12 @@ func (window *Window) compressExpose (
typedEvent, ok := untypedEvent.Event.(xproto.ExposeEvent)
if !ok { continue }
// FIXME: union all areas into the last event
if firstEvent.Window == typedEvent.Window {
region = region.Union (image.Rect (
int(typedEvent.X), int(typedEvent.Y),
int(typedEvent.X + typedEvent.Width),
int(typedEvent.Y + typedEvent.Height)))
lastEvent = typedEvent
defer func (index int) {
xevent.DequeueAt(window.backend.connection, index)

View File

@ -12,6 +12,7 @@ import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/config"
import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/elements"
// import "runtime/debug"
type Window struct {
backend *Backend
@ -290,6 +291,7 @@ func (window *Window) childDrawCallback (region canvas.Canvas) {
func (window *Window) paste (canvas canvas.Canvas) (updatedRegion image.Rectangle) {
data, stride := canvas.Buffer()
bounds := canvas.Bounds().Intersect(window.xCanvas.Bounds())
// debug.PrintStack()
for x := bounds.Min.X; x < bounds.Max.X; x ++ {
for y := bounds.Min.Y; y < bounds.Max.Y; y ++ {
rgba := data[x + y * stride]

View File

@ -150,7 +150,7 @@ func run () {
window.OnClose(tomo.Stop)
window.Show()
go func () {
http.ListenAndServe("localhost:6060", nil)
http.ListenAndServe("localhost:9090", nil)
} ()
}