It displays things on a screen
This commit is contained in:
parent
208c50a66b
commit
4c79d6772c
2
box.go
2
box.go
@ -237,9 +237,11 @@ func (this *box) recursiveRedo () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *box) invalidateDraw () {
|
func (this *box) invalidateDraw () {
|
||||||
|
if this.parent == nil { return }
|
||||||
this.parent.window().invalidateDraw(this)
|
this.parent.window().invalidateDraw(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *box) invalidateLayout () {
|
func (this *box) invalidateLayout () {
|
||||||
|
if this.parent == nil { return }
|
||||||
this.parent.window().invalidateLayout(this)
|
this.parent.window().invalidateLayout(this)
|
||||||
}
|
}
|
||||||
|
@ -14,18 +14,19 @@ type Canvas struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new canvas from a bounding rectangle.
|
// New creates a new canvas from a bounding rectangle.
|
||||||
func New (x *xgbutil.XUtil, bounds image.Rectangle) Canvas {
|
func New (x *xgbutil.XUtil, bounds image.Rectangle) *Canvas {
|
||||||
return Canvas { xgraphics.New(x, bounds) }
|
return NewFrom(xgraphics.New(x, bounds))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFrom creates a new canvas from an existing xgraphics.Image.
|
// NewFrom creates a new canvas from an existing xgraphics.Image.
|
||||||
func NewFrom (image *xgraphics.Image) Canvas {
|
func NewFrom (image *xgraphics.Image) *Canvas {
|
||||||
return Canvas { image }
|
if image == nil { return nil }
|
||||||
|
return &Canvas { image }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pen returns a new drawing context.
|
// Pen returns a new drawing context.
|
||||||
func (this Canvas) Pen () canvas.Pen {
|
func (this *Canvas) Pen () canvas.Pen {
|
||||||
return pen {
|
return &pen {
|
||||||
image: this.Image,
|
image: this.Image,
|
||||||
gfx: ggfx.Image[uint8] {
|
gfx: ggfx.Image[uint8] {
|
||||||
Pix: this.Image.Pix,
|
Pix: this.Image.Pix,
|
||||||
@ -37,16 +38,25 @@ func (this Canvas) Pen () canvas.Pen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clip returns a sub-canvas of this canvas.
|
// Clip returns a sub-canvas of this canvas.
|
||||||
func (this Canvas) Clip (bounds image.Rectangle) canvas.Canvas {
|
func (this *Canvas) Clip (bounds image.Rectangle) canvas.Canvas {
|
||||||
return Canvas { this.Image.SubImage(bounds).(*xgraphics.Image) }
|
this.assert()
|
||||||
|
subImage := this.Image.SubImage(bounds)
|
||||||
|
if subImage == nil { return nil }
|
||||||
|
xImage := subImage.(*xgraphics.Image)
|
||||||
|
return &Canvas { xImage }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push pushes this canvas to the screen.
|
// Push pushes this canvas to the screen.
|
||||||
func (this Canvas) Push (window xproto.Window) {
|
func (this *Canvas) Push (window xproto.Window) {
|
||||||
|
this.assert()
|
||||||
this.XDraw()
|
this.XDraw()
|
||||||
this.XExpPaint(window, this.Bounds().Min.X, this.Bounds().Min.Y)
|
this.XExpPaint(window, this.Bounds().Min.X, this.Bounds().Min.Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Canvas) assert () {
|
||||||
|
if this == nil { panic("nil canvas") }
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: we need to implement:
|
// TODO: we need to implement:
|
||||||
// - cap
|
// - cap
|
||||||
// - joint
|
// - joint
|
||||||
@ -65,7 +75,7 @@ type pen struct {
|
|||||||
fill [4]uint8
|
fill [4]uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this pen) Rectangle (bounds image.Rectangle) {
|
func (this *pen) Rectangle (bounds image.Rectangle) {
|
||||||
if this.weight == 0 {
|
if this.weight == 0 {
|
||||||
this.gfx.FillRectangle(this.fill[:], bounds)
|
this.gfx.FillRectangle(this.fill[:], bounds)
|
||||||
} else {
|
} else {
|
||||||
@ -73,7 +83,7 @@ func (this pen) Rectangle (bounds image.Rectangle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this pen) Path (points ...image.Point) {
|
func (this *pen) Path (points ...image.Point) {
|
||||||
if this.weight == 0 {
|
if this.weight == 0 {
|
||||||
this.gfx.FillPolygon(this.fill[:], points...)
|
this.gfx.FillPolygon(this.fill[:], points...)
|
||||||
} else if this.closed {
|
} else if this.closed {
|
||||||
@ -83,21 +93,21 @@ func (this pen) Path (points ...image.Point) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this pen) Closed (closed bool) { this.closed = closed }
|
func (this *pen) Closed (closed bool) { this.closed = closed }
|
||||||
func (this pen) Cap (endCap canvas.Cap) { this.endCap = endCap }
|
func (this *pen) Cap (endCap canvas.Cap) { this.endCap = endCap }
|
||||||
func (this pen) Joint (joint canvas.Joint) { this.joint = joint }
|
func (this *pen) Joint (joint canvas.Joint) { this.joint = joint }
|
||||||
func (this pen) StrokeWeight (weight int) { this.weight = weight }
|
func (this *pen) StrokeWeight (weight int) { this.weight = weight }
|
||||||
func (this pen) StrokeAlign (align canvas.StrokeAlign) { this.align = align }
|
func (this *pen) StrokeAlign (align canvas.StrokeAlign) { this.align = align }
|
||||||
|
|
||||||
func (this pen) Stroke (stroke color.Color) { this.stroke = convertColor(stroke) }
|
func (this *pen) Stroke (stroke color.Color) { this.stroke = convertColor(stroke) }
|
||||||
func (this pen) Fill (fill color.Color) { this.fill = convertColor(fill) }
|
func (this *pen) Fill (fill color.Color) { this.fill = convertColor(fill) }
|
||||||
|
|
||||||
func convertColor (c color.Color) [4]uint8 {
|
func convertColor (c color.Color) [4]uint8 {
|
||||||
r, g, b, a := c.RGBA()
|
r, g, b, a := c.RGBA()
|
||||||
return [4]uint8 {
|
return [4]uint8 {
|
||||||
uint8(b >> 8),
|
uint8(b >> 8),
|
||||||
uint8(g >> 8),
|
uint8(g >> 8),
|
||||||
uint8(a >> 8),
|
|
||||||
uint8(r >> 8),
|
uint8(r >> 8),
|
||||||
|
uint8(a >> 8),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
event.go
7
event.go
@ -10,8 +10,11 @@ func (window *window) handleExpose (
|
|||||||
connection *xgbutil.XUtil,
|
connection *xgbutil.XUtil,
|
||||||
event xevent.ExposeEvent,
|
event xevent.ExposeEvent,
|
||||||
) {
|
) {
|
||||||
|
if window.xCanvas == nil {
|
||||||
|
window.reallocateCanvas()
|
||||||
|
}
|
||||||
window.compressExpose(*event.ExposeEvent)
|
window.compressExpose(*event.ExposeEvent)
|
||||||
window.xCanvas.Push(window.xWindow.Id)
|
window.pushAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (window *window) updateBounds () {
|
func (window *window) updateBounds () {
|
||||||
@ -46,7 +49,7 @@ func (window *window) handleConfigureNotify (
|
|||||||
if sizeChanged {
|
if sizeChanged {
|
||||||
configureEvent = window.compressConfigureNotify(configureEvent)
|
configureEvent = window.compressConfigureNotify(configureEvent)
|
||||||
window.reallocateCanvas()
|
window.reallocateCanvas()
|
||||||
window.root.SetBounds(window.metrics.bounds)
|
|
||||||
// TODO figure out what to do with this
|
// TODO figure out what to do with this
|
||||||
// if !window.exposeEventFollows(configureEvent) {
|
// if !window.exposeEventFollows(configureEvent) {
|
||||||
// }
|
// }
|
||||||
|
32
system.go
32
system.go
@ -2,7 +2,6 @@ package x
|
|||||||
|
|
||||||
import "image"
|
import "image"
|
||||||
import "git.tebibyte.media/tomo/tomo"
|
import "git.tebibyte.media/tomo/tomo"
|
||||||
import "git.tebibyte.media/tomo/x/canvas"
|
|
||||||
import "git.tebibyte.media/tomo/tomo/canvas"
|
import "git.tebibyte.media/tomo/tomo/canvas"
|
||||||
|
|
||||||
type boxSet map[anyBox] struct { }
|
type boxSet map[anyBox] struct { }
|
||||||
@ -46,11 +45,17 @@ type anyBox interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (window *window) SetRoot (root tomo.Object) {
|
func (window *window) SetRoot (root tomo.Object) {
|
||||||
box := root.Box().(anyBox)
|
if window.root != nil {
|
||||||
window.root.setParent(nil)
|
window.root.setParent(nil)
|
||||||
box.setParent(window)
|
}
|
||||||
window.invalidateLayout(box)
|
if root == nil {
|
||||||
window.root = box
|
window.root = nil
|
||||||
|
} else {
|
||||||
|
box := root.Box().(anyBox)
|
||||||
|
box.setParent(window)
|
||||||
|
window.invalidateLayout(box)
|
||||||
|
window.root = box
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (window *window) window () *window {
|
func (window *window) window () *window {
|
||||||
@ -78,11 +83,20 @@ func (window *window) focus (box anyBox) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (window *window) afterEvent () {
|
func (window *window) afterEvent () {
|
||||||
|
if window.xCanvas == nil { return }
|
||||||
|
|
||||||
if window.needRedo {
|
if window.needRedo {
|
||||||
|
// set child bounds
|
||||||
|
childBounds := window.metrics.bounds
|
||||||
|
childBounds = childBounds.Sub(childBounds.Min)
|
||||||
|
window.root.SetBounds(childBounds)
|
||||||
|
|
||||||
|
// full relayout/redraw
|
||||||
if window.root != nil {
|
if window.root != nil {
|
||||||
window.root.recursiveRedo()
|
window.root.recursiveRedo()
|
||||||
}
|
}
|
||||||
window.xCanvas.Push(window.xWindow.Id)
|
window.pushAll()
|
||||||
|
window.needRedo = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,5 +109,7 @@ func (window *window) afterEvent () {
|
|||||||
box.doDraw()
|
box.doDraw()
|
||||||
toPush = toPush.Union(box.Bounds())
|
toPush = toPush.Union(box.Bounds())
|
||||||
}
|
}
|
||||||
window.xCanvas.Clip(toPush).(xcanvas.Canvas).Push(window.xWindow.Id)
|
if !toPush.Empty() {
|
||||||
|
window.pushRegion(toPush)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
50
window.go
50
window.go
@ -24,7 +24,7 @@ type window struct {
|
|||||||
backend *Backend
|
backend *Backend
|
||||||
xWindow *xwindow.Window
|
xWindow *xwindow.Window
|
||||||
xImage *xgraphics.Image
|
xImage *xgraphics.Image
|
||||||
xCanvas xcanvas.Canvas
|
xCanvas *xcanvas.Canvas
|
||||||
|
|
||||||
title string
|
title string
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ func (backend *Backend) NewWindow (
|
|||||||
output tomo.MainWindow,
|
output tomo.MainWindow,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
if backend == nil { panic("nil backend") }
|
backend.assert()
|
||||||
window, err := backend.newWindow(bounds, false)
|
window, err := backend.newWindow(bounds, false)
|
||||||
|
|
||||||
output = mainWindow { window: window }
|
output = mainWindow { window: window }
|
||||||
@ -104,10 +104,10 @@ func (backend *Backend) newWindow (
|
|||||||
window.Close()
|
window.Close()
|
||||||
})
|
})
|
||||||
|
|
||||||
// xevent.ExposeFun(window.handleExpose).
|
xevent.ExposeFun(window.handleExpose).
|
||||||
// Connect(backend.x, window.xWindow.Id)
|
Connect(backend.x, window.xWindow.Id)
|
||||||
// xevent.ConfigureNotifyFun(window.handleConfigureNotify).
|
xevent.ConfigureNotifyFun(window.handleConfigureNotify).
|
||||||
// Connect(backend.x, window.xWindow.Id)
|
Connect(backend.x, window.xWindow.Id)
|
||||||
// xevent.KeyPressFun(window.handleKeyPress).
|
// xevent.KeyPressFun(window.handleKeyPress).
|
||||||
// Connect(backend.x, window.xWindow.Id)
|
// Connect(backend.x, window.xWindow.Id)
|
||||||
// xevent.KeyReleaseFun(window.handleKeyRelease).
|
// xevent.KeyReleaseFun(window.handleKeyRelease).
|
||||||
@ -130,8 +130,6 @@ func (backend *Backend) newWindow (
|
|||||||
window.metrics.bounds = bounds
|
window.metrics.bounds = bounds
|
||||||
window.setMinimumSize(8, 8)
|
window.setMinimumSize(8, 8)
|
||||||
|
|
||||||
window.reallocateCanvas()
|
|
||||||
|
|
||||||
backend.windows[window.xWindow.Id] = window
|
backend.windows[window.xWindow.Id] = window
|
||||||
|
|
||||||
output = window
|
output = window
|
||||||
@ -243,14 +241,6 @@ func (window *window) Paste (callback func (data.Data, error), accept ...data.Mi
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (window *window) Show () {
|
func (window *window) Show () {
|
||||||
// fill the screen with black if there is no active child
|
|
||||||
if window.root == nil {
|
|
||||||
window.xCanvas.For (func (x, y int) xgraphics.BGRA {
|
|
||||||
return xgraphics.BGRA { }
|
|
||||||
})
|
|
||||||
window.xCanvas.Push(window.xWindow.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
window.xWindow.Map()
|
window.xWindow.Map()
|
||||||
if window.shy { window.grabInput() }
|
if window.shy { window.grabInput() }
|
||||||
}
|
}
|
||||||
@ -314,8 +304,11 @@ func (window *window) setClientLeader (leader *window) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (window *window) reallocateCanvas () {
|
func (window *window) reallocateCanvas () {
|
||||||
previousWidth := window.xCanvas.Bounds().Dx()
|
var previousWidth, previousHeight int
|
||||||
previousHeight := window.xCanvas.Bounds().Dy()
|
if window.xCanvas != nil {
|
||||||
|
previousWidth = window.xCanvas.Bounds().Dx()
|
||||||
|
previousHeight = window.xCanvas.Bounds().Dy()
|
||||||
|
}
|
||||||
|
|
||||||
newWidth := window.metrics.bounds.Dx()
|
newWidth := window.metrics.bounds.Dx()
|
||||||
newHeight := window.metrics.bounds.Dy()
|
newHeight := window.metrics.bounds.Dy()
|
||||||
@ -325,7 +318,7 @@ func (window *window) reallocateCanvas () {
|
|||||||
allocStep := 128
|
allocStep := 128
|
||||||
|
|
||||||
if larger || smaller {
|
if larger || smaller {
|
||||||
if window.xCanvas.Image != nil {
|
if window.xCanvas != nil {
|
||||||
window.xCanvas.Destroy()
|
window.xCanvas.Destroy()
|
||||||
}
|
}
|
||||||
window.xCanvas = xcanvas.NewFrom(xgraphics.New (
|
window.xCanvas = xcanvas.NewFrom(xgraphics.New (
|
||||||
@ -336,9 +329,28 @@ func (window *window) reallocateCanvas () {
|
|||||||
(newHeight / allocStep + 1) * allocStep)))
|
(newHeight / allocStep + 1) * allocStep)))
|
||||||
window.xCanvas.CreatePixmap()
|
window.xCanvas.CreatePixmap()
|
||||||
}
|
}
|
||||||
|
|
||||||
window.needRedo = true
|
window.needRedo = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (window *window) pushAll () {
|
||||||
|
if window.xCanvas != nil {
|
||||||
|
window.xCanvas.Push(window.xWindow.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (window *window) pushRegion (region image.Rectangle) {
|
||||||
|
if window.xCanvas == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
subCanvas := window.xCanvas.Clip(region)
|
||||||
|
if subCanvas == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
subCanvas.(*xcanvas.Canvas).Push(window.xWindow.Id)
|
||||||
|
}
|
||||||
|
|
||||||
func (window *window) setMinimumSize (width, height int) {
|
func (window *window) setMinimumSize (width, height int) {
|
||||||
if width < 8 { width = 8 }
|
if width < 8 { width = 8 }
|
||||||
if height < 8 { height = 8 }
|
if height < 8 { height = 8 }
|
||||||
|
Reference in New Issue
Block a user