Added mouse button press input

This commit is contained in:
Sasha Koshka 2022-11-12 19:02:24 -05:00
parent 47ee6545cb
commit 48510db209
3 changed files with 150 additions and 79 deletions

View File

@ -1,6 +1,7 @@
package x package x
import "os" import "os"
// import "fmt"
import "sync" import "sync"
import "image" import "image"
import "image/draw" 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/opentype"
import "golang.org/x/image/font/basicfont" 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/xgbutil"
import "github.com/jezek/xgb/xproto" import "github.com/jezek/xgb/xproto"
import "github.com/jezek/xgbutil/ewmh" import "github.com/jezek/xgbutil/ewmh"
@ -31,12 +32,6 @@ type Backend struct {
drawLock sync.Mutex drawLock sync.Mutex
ping struct {
before chan(struct { })
after chan(struct { })
quit chan(struct { })
}
font struct { font struct {
face font.Face face font.Face
} }
@ -62,30 +57,8 @@ type Backend struct {
func (backend *Backend) Run (channel chan(stone.Event)) { func (backend *Backend) Run (channel chan(stone.Event)) {
backend.channel = channel backend.channel = channel
xevent.Main(backend.connection)
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() backend.shutDown()
return
}
}
} }
func (backend *Backend) Draw () { func (backend *Backend) Draw () {
@ -104,10 +77,6 @@ func (backend *Backend) Draw () {
backend.canvas.XDraw() backend.canvas.XDraw()
backend.canvas.XPaint(backend.window.Id) backend.canvas.XPaint(backend.window.Id)
} else { } 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)...) backend.updateWindowAreas(backend.drawCells(false)...)
} }
} }
@ -154,10 +123,11 @@ func (backend *Backend) SetIcon (icons []image.Image) (err error) {
return return
} }
func (backend *Backend) handleXEvent (event xgb.Event) { func (backend *Backend) handleConfigureNotify (
switch event.(type) { connection *xgbutil.XUtil,
case xproto.ConfigureNotifyEvent: event xevent.ConfigureNotifyEvent,
configureEvent := event.(xproto.ConfigureNotifyEvent) ) {
configureEvent := *event.ConfigureNotifyEvent
newWidth := int(configureEvent.Width) newWidth := int(configureEvent.Width)
newHeight := int(configureEvent.Height) newHeight := int(configureEvent.Height)
@ -174,6 +144,21 @@ func (backend *Backend) handleXEvent (event xgb.Event) {
backend.channel <- stone.EventResize { } 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 ( func (backend *Backend) compressConfigureNotify (
@ -253,7 +238,8 @@ func (backend *Backend) drawCells (forceRedraw bool) (areas []image.Rectangle) {
cell := backend.application.Cell(x, y) cell := backend.application.Cell(x, y)
content := cell.Rune() content := cell.Rune()
if content < 32 { continue }
if forceRedraw && content < 32 { continue }
areas = append(areas, backend.boundsOfCell(x, y)) areas = append(areas, backend.boundsOfCell(x, y))
backend.drawRune(x, y, content) backend.drawRune(x, y, content)
@ -269,13 +255,6 @@ func (backend *Backend) drawRune (x, y int, character rune) {
// TODO: cache these draws as non-transparent buffers with the // TODO: cache these draws as non-transparent buffers with the
// application background color as the background. that way, we won't // application background color as the background. that way, we won't
// need to redraw the characters *or* composite them. // need to redraw the characters *or* composite them.
origin := backend.originOfCell(x, y + 1)
destinationRectangle, mask, maskPoint, _, _ := backend.font.face.Glyph (
fixed.Point26_6 {
X: fixed.I(origin.X),
Y: fixed.I(origin.Y - backend.metrics.descent),
},
character)
fillRectangle ( fillRectangle (
&image.Uniform { &image.Uniform {
@ -284,6 +263,16 @@ func (backend *Backend) drawRune (x, y int, character rune) {
backend.canvas, backend.canvas,
backend.boundsOfCell(x, y)) backend.boundsOfCell(x, y))
if character < 32 { return }
origin := backend.originOfCell(x, y + 1)
destinationRectangle, mask, maskPoint, _, _ := backend.font.face.Glyph (
fixed.Point26_6 {
X: fixed.I(origin.X),
Y: fixed.I(origin.Y - backend.metrics.descent),
},
character)
// strokeRectangle ( // strokeRectangle (
// &image.Uniform { // &image.Uniform {
// C: backend.config.Color(stone.ColorForeground), // 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, backend.metrics.windowWidth, backend.metrics.windowHeight,
0) 0)
backend.window.Map() 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.SetTitle(application.Title())
backend.SetIcon(application.Icon()) backend.SetIcon(application.Icon())
@ -395,10 +393,13 @@ func factory (application *stone.Application) (output stone.Backend, err error)
backend.shutDown() backend.shutDown()
}) })
// start event loop // attatch event handlers
backend.ping.before, xevent.ConfigureNotifyFun(backend.handleConfigureNotify).
backend.ping.after, Connect(backend.connection, backend.window.Id)
backend.ping.quit = xevent.MainPing(backend.connection) xevent.ButtonPressFun(backend.handleButtonPress).
Connect(backend.connection, backend.window.Id)
xevent.ButtonReleaseFun(backend.handleButtonRelease).
Connect(backend.connection, backend.window.Id)
output = backend output = backend
return 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 package stone
// These should be identical to the glfw keys
type Button int type Button int
const ( const (
@ -129,15 +127,22 @@ const (
KeyRightSuper Button = 257 KeyRightSuper Button = 257
KeyMenu Button = 256 KeyMenu Button = 256
MouseButton1 Button = 0 MouseButton1 Button = 1
MouseButton2 Button = 1 MouseButton2 Button = 2
MouseButton3 Button = 2 MouseButton3 Button = 3
MouseButton4 Button = 3 MouseButton4 Button = 4
MouseButton5 Button = 4 MouseButton5 Button = 5
MouseButton6 Button = 5 MouseButton6 Button = 6
MouseButton7 Button = 6 MouseButton7 Button = 7
MouseButton8 Button = 7 MouseButton8 Button = 8
MouseButton9 Button = 9
MouseButtonLeft Button = MouseButton1 MouseButtonLeft Button = MouseButton1
MouseButtonRight Button = MouseButton2 MouseButtonMiddle Button = MouseButton2
MouseButtonMiddle Button = MouseButton3 MouseButtonRight Button = MouseButton3
MouseButtonScrollUp Button = MouseButton4
MouseButtonScrollDown Button = MouseButton5
MouseButtonScrollLeft Button = MouseButton6
MouseButtonScrollRight Button = MouseButton7
MouseButtonBack Button = MouseButton8
MouseButtonForward Button = MouseButton9
) )