x-backend #2

Merged
sashakoshka merged 34 commits from x-backend into main 2022-11-14 21:40:25 -07:00
3 changed files with 150 additions and 79 deletions
Showing only changes of commit 48510db209 - Show all commits

View File

@ -1,6 +1,7 @@
package x
import "os"
// import "fmt"
import "sync"
import "image"
import "image/draw"
@ -9,7 +10,7 @@ import "golang.org/x/image/math/fixed"
import "golang.org/x/image/font/opentype"
import "golang.org/x/image/font/basicfont"
import "github.com/jezek/xgb"
// import "github.com/jezek/xgb"
import "github.com/jezek/xgbutil"
import "github.com/jezek/xgb/xproto"
import "github.com/jezek/xgbutil/ewmh"
@ -31,12 +32,6 @@ type Backend struct {
drawLock sync.Mutex
ping struct {
before chan(struct { })
after chan(struct { })
quit chan(struct { })
}
font struct {
face font.Face
}
@ -62,30 +57,8 @@ type Backend struct {
func (backend *Backend) Run (channel chan(stone.Event)) {
backend.channel = channel
for {
select {
case <- backend.ping.before:
// if the queue is empty, don't dequeue anything because
// it would cause a fucking segfault lmao (???)
if !xevent.Empty(backend.connection) {
event, err := xevent.Dequeue(backend.connection)
if err != nil {
// TODO: do something with err
}
if event != nil {
backend.handleXEvent(event)
}
}
<- backend.ping.after
case <- backend.ping.quit:
backend.shutDown()
return
}
}
xevent.Main(backend.connection)
backend.shutDown()
}
func (backend *Backend) Draw () {
@ -104,10 +77,6 @@ func (backend *Backend) Draw () {
backend.canvas.XDraw()
backend.canvas.XPaint(backend.window.Id)
} else {
// backend.drawCells(false)
// backend.canvas.XDraw()
// backend.canvas.XPaint(backend.window.Id)
// FIXME use this instead once it works
backend.updateWindowAreas(backend.drawCells(false)...)
}
}
@ -154,28 +123,44 @@ func (backend *Backend) SetIcon (icons []image.Image) (err error) {
return
}
func (backend *Backend) handleXEvent (event xgb.Event) {
switch event.(type) {
case xproto.ConfigureNotifyEvent:
configureEvent := event.(xproto.ConfigureNotifyEvent)
newWidth := int(configureEvent.Width)
newHeight := int(configureEvent.Height)
sizeChanged :=
backend.metrics.windowWidth != newWidth ||
backend.metrics.windowHeight != newHeight
backend.metrics.windowWidth = newWidth
backend.metrics.windowHeight = newHeight
func (backend *Backend) handleConfigureNotify (
connection *xgbutil.XUtil,
event xevent.ConfigureNotifyEvent,
) {
configureEvent := *event.ConfigureNotifyEvent
newWidth := int(configureEvent.Width)
newHeight := int(configureEvent.Height)
sizeChanged :=
backend.metrics.windowWidth != newWidth ||
backend.metrics.windowHeight != newHeight
backend.metrics.windowWidth = newWidth
backend.metrics.windowHeight = newHeight
if sizeChanged {
configureEvent =
backend.compressConfigureNotify(configureEvent)
backend.application.SetSize(backend.calculateBufferSize())
backend.channel <- stone.EventResize { }
}
if sizeChanged {
configureEvent =
backend.compressConfigureNotify(configureEvent)
backend.application.SetSize(backend.calculateBufferSize())
backend.channel <- stone.EventResize { }
}
}
func (backend *Backend) handleButtonPress (
connection *xgbutil.XUtil,
event xevent.ButtonPressEvent,
) {
buttonEvent := *event.ButtonPressEvent
backend.channel <- stone.EventPress(buttonEvent.Detail)
}
func (backend *Backend) handleButtonRelease (
connection *xgbutil.XUtil,
event xevent.ButtonReleaseEvent,
) {
buttonEvent := *event.ButtonReleaseEvent
backend.channel <- stone.EventRelease(buttonEvent.Detail)
}
func (backend *Backend) compressConfigureNotify (
firstEvent xproto.ConfigureNotifyEvent,
) (
@ -253,7 +238,8 @@ func (backend *Backend) drawCells (forceRedraw bool) (areas []image.Rectangle) {
cell := backend.application.Cell(x, y)
content := cell.Rune()
if content < 32 { continue }
if forceRedraw && content < 32 { continue }
areas = append(areas, backend.boundsOfCell(x, y))
backend.drawRune(x, y, content)
@ -269,6 +255,16 @@ func (backend *Backend) drawRune (x, y int, character rune) {
// TODO: cache these draws as non-transparent buffers with the
// application background color as the background. that way, we won't
// need to redraw the characters *or* composite them.
fillRectangle (
&image.Uniform {
C: backend.config.Color(stone.ColorApplication),
},
backend.canvas,
backend.boundsOfCell(x, y))
if character < 32 { return }
origin := backend.originOfCell(x, y + 1)
destinationRectangle, mask, maskPoint, _, _ := backend.font.face.Glyph (
fixed.Point26_6 {
@ -277,13 +273,6 @@ func (backend *Backend) drawRune (x, y int, character rune) {
},
character)
fillRectangle (
&image.Uniform {
C: backend.config.Color(stone.ColorApplication),
},
backend.canvas,
backend.boundsOfCell(x, y))
// strokeRectangle (
// &image.Uniform {
// C: backend.config.Color(stone.ColorForeground),
@ -382,7 +371,16 @@ func factory (application *stone.Application) (output stone.Backend, err error)
backend.metrics.windowWidth, backend.metrics.windowHeight,
0)
backend.window.Map()
backend.window.Listen(xproto.EventMaskStructureNotify)
// TODO: also listen to mouse movement (compressed) and mouse and
// keyboard buttons (uncompressed)
err = backend.window.Listen (
xproto.EventMaskStructureNotify,
// xproto.EventMaskPointerMotion,
// xproto.EventMaskKeyPress,
// xproto.EventMaskKeyRelease,
xproto.EventMaskButtonPress,
xproto.EventMaskButtonRelease,
)
backend.SetTitle(application.Title())
backend.SetIcon(application.Icon())
@ -395,10 +393,13 @@ func factory (application *stone.Application) (output stone.Backend, err error)
backend.shutDown()
})
// start event loop
backend.ping.before,
backend.ping.after,
backend.ping.quit = xevent.MainPing(backend.connection)
// attatch event handlers
xevent.ConfigureNotifyFun(backend.handleConfigureNotify).
Connect(backend.connection, backend.window.Id)
xevent.ButtonPressFun(backend.handleButtonPress).
Connect(backend.connection, backend.window.Id)
xevent.ButtonReleaseFun(backend.handleButtonRelease).
Connect(backend.connection, backend.window.Id)
output = backend
return

65
examples/draw/main.go Normal file
View File

@ -0,0 +1,65 @@
package main
import "os"
import "image"
import _ "image/png"
import "git.tebibyte.media/sashakoshka/stone"
import _ "git.tebibyte.media/sashakoshka/stone/backends/x"
var application = &stone.Application { }
var mousePressed bool
func main () {
application.SetTitle("hellorld")
application.SetSize(32, 16)
iconFile16, err := os.Open("assets/scaffold16.png")
if err != nil { panic(err) }
icon16, _, err := image.Decode(iconFile16)
if err != nil { panic(err) }
iconFile16.Close()
iconFile32, err := os.Open("assets/scaffold32.png")
if err != nil { panic(err) }
icon32, _, err := image.Decode(iconFile32)
if err != nil { panic(err) }
iconFile16.Close()
application.SetIcon([]image.Image { icon16, icon32 })
channel, err := application.Run()
if err != nil { panic(err) }
application.Draw()
for {
event := <- channel
switch event.(type) {
case stone.EventQuit:
os.Exit(0)
case stone.EventPress:
event := event.(stone.EventPress)
if stone.Button(event) == stone.MouseButtonLeft {
mousePressed = true
application.SetRune(0, 0, '+')
application.Draw()
}
case stone.EventRelease:
event := event.(stone.EventRelease)
if stone.Button(event) == stone.MouseButtonLeft {
mousePressed = false
application.SetRune(0, 0, 0)
application.Draw()
}
case stone.EventMouseMove:
event := event.(stone.EventMouseMove)
application.SetRune(event.X, event.Y, '#')
application.Draw()
case stone.EventResize:
application.Draw()
}
}
}

View File

@ -1,7 +1,5 @@
package stone
// These should be identical to the glfw keys
type Button int
const (
@ -129,15 +127,22 @@ const (
KeyRightSuper Button = 257
KeyMenu Button = 256
MouseButton1 Button = 0
MouseButton2 Button = 1
MouseButton3 Button = 2
MouseButton4 Button = 3
MouseButton5 Button = 4
MouseButton6 Button = 5
MouseButton7 Button = 6
MouseButton8 Button = 7
MouseButtonLeft Button = MouseButton1
MouseButtonRight Button = MouseButton2
MouseButtonMiddle Button = MouseButton3
MouseButton1 Button = 1
MouseButton2 Button = 2
MouseButton3 Button = 3
MouseButton4 Button = 4
MouseButton5 Button = 5
MouseButton6 Button = 6
MouseButton7 Button = 7
MouseButton8 Button = 8
MouseButton9 Button = 9
MouseButtonLeft Button = MouseButton1
MouseButtonMiddle Button = MouseButton2
MouseButtonRight Button = MouseButton3
MouseButtonScrollUp Button = MouseButton4
MouseButtonScrollDown Button = MouseButton5
MouseButtonScrollLeft Button = MouseButton6
MouseButtonScrollRight Button = MouseButton7
MouseButtonBack Button = MouseButton8
MouseButtonForward Button = MouseButton9
)