215 lines
5.3 KiB
Go
215 lines
5.3 KiB
Go
package x
|
|
|
|
import "image"
|
|
|
|
import "github.com/jezek/xgbutil"
|
|
import "github.com/jezek/xgb/xproto"
|
|
import "github.com/jezek/xgbutil/xevent"
|
|
|
|
import "git.tebibyte.media/sashakoshka/stone"
|
|
|
|
type scrollSum struct {
|
|
x, y int
|
|
}
|
|
|
|
func (sum *scrollSum) add (button xproto.Button) {
|
|
switch button {
|
|
case 4:
|
|
sum.y --
|
|
case 5:
|
|
sum.y ++
|
|
case 6:
|
|
sum.x --
|
|
case 7:
|
|
sum.x ++
|
|
}
|
|
}
|
|
|
|
func (backend *Backend) Run () {
|
|
backend.callbackManager.RunStart()
|
|
backend.Draw()
|
|
xevent.Main(backend.connection)
|
|
backend.callbackManager.RunQuit()
|
|
}
|
|
|
|
func (backend *Backend) handleConfigureNotify (
|
|
connection *xgbutil.XUtil,
|
|
event xevent.ConfigureNotifyEvent,
|
|
) {
|
|
backend.lock.Lock()
|
|
|
|
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)
|
|
|
|
// resize buffer
|
|
width, height := backend.calculateBufferSize()
|
|
backend.application.SetSize(width, height)
|
|
|
|
if backend.config.Center() {
|
|
// position buffer in the center of the screen
|
|
frameWidth := width * backend.metrics.cellWidth
|
|
frameHeight := height * backend.metrics.cellHeight
|
|
backend.metrics.paddingX =
|
|
(backend.metrics.windowWidth - frameWidth) / 2
|
|
backend.metrics.paddingY =
|
|
(backend.metrics.windowHeight - frameHeight) / 2
|
|
} else {
|
|
backend.metrics.paddingX = backend.metrics.padding
|
|
backend.metrics.paddingY = backend.metrics.padding
|
|
}
|
|
|
|
backend.windowBoundsClean = false
|
|
}
|
|
|
|
backend.lock.Unlock()
|
|
|
|
if sizeChanged {
|
|
backend.callbackManager.RunResize()
|
|
backend.Draw()
|
|
}
|
|
}
|
|
|
|
func (backend *Backend) handleButtonPress (
|
|
connection *xgbutil.XUtil,
|
|
event xevent.ButtonPressEvent,
|
|
) {
|
|
buttonEvent := *event.ButtonPressEvent
|
|
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 {
|
|
sum := scrollSum { }
|
|
sum.add(buttonEvent.Detail)
|
|
backend.compressScrollSum(&sum)
|
|
backend.callbackManager.RunScroll(sum.x, sum.y)
|
|
} else {
|
|
backend.callbackManager.RunPress (
|
|
stone.Button(buttonEvent.Detail + 127),
|
|
stone.Modifiers { })
|
|
}
|
|
}
|
|
|
|
func (backend *Backend) handleButtonRelease (
|
|
connection *xgbutil.XUtil,
|
|
event xevent.ButtonReleaseEvent,
|
|
) {
|
|
buttonEvent := *event.ButtonReleaseEvent
|
|
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { return }
|
|
backend.callbackManager.RunRelease(stone.Button(buttonEvent.Detail + 127))
|
|
}
|
|
|
|
func (backend *Backend) handleKeyPress (
|
|
connection *xgbutil.XUtil,
|
|
event xevent.KeyPressEvent,
|
|
) {
|
|
keyEvent := *event.KeyPressEvent
|
|
button, num := backend.keycodeToButton(keyEvent.Detail, keyEvent.State)
|
|
backend.callbackManager.RunPress (button, stone.Modifiers {
|
|
// FIXME these may not be correct in all cases
|
|
Shift: (keyEvent.State & xproto.ModMaskShift) > 0,
|
|
Control: (keyEvent.State & xproto.ModMaskControl) > 0,
|
|
Alt: (keyEvent.State & xproto.ModMask1) > 0,
|
|
// Meta: (keyEvent.State & xproto.??) > 0,
|
|
Super: (keyEvent.State & xproto.ModMask4) > 0,
|
|
// Hyper: (keyEvent.State & xproto.??) > 0,
|
|
NumberPad: num,
|
|
})
|
|
}
|
|
|
|
func (backend *Backend) handleKeyRelease (
|
|
connection *xgbutil.XUtil,
|
|
event xevent.KeyReleaseEvent,
|
|
) {
|
|
keyEvent := *event.KeyReleaseEvent
|
|
button, _ := backend.keycodeToButton(keyEvent.Detail, keyEvent.State)
|
|
backend.callbackManager.RunRelease(button)
|
|
}
|
|
|
|
func (backend *Backend) handleMotionNotify (
|
|
connection *xgbutil.XUtil,
|
|
event xevent.MotionNotifyEvent,
|
|
) {
|
|
motionEvent := backend.compressMotionNotify(*event.MotionNotifyEvent)
|
|
x, y := backend.cellAt (image.Point {
|
|
X: int(motionEvent.EventX),
|
|
Y: int(motionEvent.EventY),
|
|
})
|
|
backend.callbackManager.RunMouseMove(x, y)
|
|
}
|
|
|
|
func (backend *Backend) compressConfigureNotify (
|
|
firstEvent xproto.ConfigureNotifyEvent,
|
|
) (
|
|
lastEvent xproto.ConfigureNotifyEvent,
|
|
) {
|
|
backend.connection.Sync()
|
|
xevent.Read(backend.connection, false)
|
|
lastEvent = firstEvent
|
|
|
|
for index, untypedEvent := range xevent.Peek(backend.connection) {
|
|
if untypedEvent.Err != nil { continue }
|
|
|
|
typedEvent, ok := untypedEvent.Event.(xproto.ConfigureNotifyEvent)
|
|
if !ok { continue }
|
|
|
|
lastEvent = typedEvent
|
|
defer func (index int) {
|
|
xevent.DequeueAt(backend.connection, index)
|
|
} (index)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (backend *Backend) compressMotionNotify (
|
|
firstEvent xproto.MotionNotifyEvent,
|
|
) (
|
|
lastEvent xproto.MotionNotifyEvent,
|
|
) {
|
|
backend.connection.Sync()
|
|
xevent.Read(backend.connection, false)
|
|
lastEvent = firstEvent
|
|
|
|
for index, untypedEvent := range xevent.Peek(backend.connection) {
|
|
if untypedEvent.Err != nil { continue }
|
|
|
|
typedEvent, ok := untypedEvent.Event.(xproto.MotionNotifyEvent)
|
|
if !ok { continue }
|
|
|
|
lastEvent = typedEvent
|
|
defer func (index int) {
|
|
xevent.DequeueAt(backend.connection, index)
|
|
} (index)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (backend *Backend) compressScrollSum (sum *scrollSum) {
|
|
backend.connection.Sync()
|
|
xevent.Read(backend.connection, false)
|
|
|
|
|
|
for index, untypedEvent := range xevent.Peek(backend.connection) {
|
|
if untypedEvent.Err != nil { continue }
|
|
|
|
typedEvent, ok := untypedEvent.Event.(xproto.ButtonPressEvent)
|
|
if !ok { continue }
|
|
|
|
sum.add(typedEvent.Detail)
|
|
defer func (index int) {
|
|
xevent.DequeueAt(backend.connection, index)
|
|
} (index)
|
|
}
|
|
|
|
return
|
|
}
|