This repository has been archived on 2023-08-08. You can view files and clone it, but cannot push or open issues or pull requests.
tomo-old/backends/x/event.go
2023-01-11 22:30:14 -05:00

259 lines
6.6 KiB
Go

package x
import "git.tebibyte.media/sashakoshka/tomo"
import "github.com/jezek/xgbutil"
import "github.com/jezek/xgb/xproto"
import "github.com/jezek/xgbutil/xevent"
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 (window *Window) handleConfigureNotify (
connection *xgbutil.XUtil,
event xevent.ConfigureNotifyEvent,
) {
configureEvent := *event.ConfigureNotifyEvent
newWidth := int(configureEvent.Width)
newHeight := int(configureEvent.Height)
sizeChanged :=
window.metrics.width != newWidth ||
window.metrics.height != newHeight
window.metrics.width = newWidth
window.metrics.height = newHeight
if sizeChanged {
configureEvent = window.compressConfigureNotify(configureEvent)
window.metrics.width = int(configureEvent.Width)
window.metrics.height = int(configureEvent.Height)
window.reallocateCanvas()
window.resizeChildToFit()
}
}
func (window *Window) handleKeyPress (
connection *xgbutil.XUtil,
event xevent.KeyPressEvent,
) {
if window.child == nil { return}
keyEvent := *event.KeyPressEvent
key, numberPad := window.backend.keycodeToKey(keyEvent.Detail, keyEvent.State)
modifiers := tomo.Modifiers {
Shift:
(keyEvent.State & xproto.ModMaskShift) > 0 ||
(keyEvent.State & window.backend.modifierMasks.shiftLock) > 0,
Control: (keyEvent.State & xproto.ModMaskControl) > 0,
Alt: (keyEvent.State & window.backend.modifierMasks.alt) > 0,
Meta: (keyEvent.State & window.backend.modifierMasks.meta) > 0,
Super: (keyEvent.State & window.backend.modifierMasks.super) > 0,
Hyper: (keyEvent.State & window.backend.modifierMasks.hyper) > 0,
NumberPad: numberPad,
}
keyDownEvent := tomo.EventKeyDown {
Key: key,
Modifiers: modifiers,
Repeated: false, // FIXME: return correct value here
}
if keyDownEvent.Key == tomo.KeyTab && keyDownEvent.Modifiers.Alt {
if window.child.Selectable() {
direction := 1
if keyDownEvent.Modifiers.Shift {
direction = -1
}
window.advanceSelectionInChild(direction)
}
} else {
window.child.Handle(keyDownEvent)
}
}
func (window *Window) advanceSelectionInChild (direction int) {
if window.child.Selected() {
if !window.child.AdvanceSelection(direction) {
window.child.Handle(tomo.EventDeselect { })
}
} else {
window.child.Handle(tomo.EventSelect { })
}
}
func (window *Window) handleKeyRelease (
connection *xgbutil.XUtil,
event xevent.KeyReleaseEvent,
) {
if window.child == nil { return }
keyEvent := *event.KeyReleaseEvent
key, numberPad := window.backend.keycodeToKey(keyEvent.Detail, keyEvent.State)
modifiers := tomo.Modifiers {
Shift:
(keyEvent.State & xproto.ModMaskShift) > 0 ||
(keyEvent.State & window.backend.modifierMasks.shiftLock) > 0,
Control: (keyEvent.State & xproto.ModMaskControl) > 0,
Alt: (keyEvent.State & window.backend.modifierMasks.alt) > 0,
Meta: (keyEvent.State & window.backend.modifierMasks.meta) > 0,
Super: (keyEvent.State & window.backend.modifierMasks.super) > 0,
Hyper: (keyEvent.State & window.backend.modifierMasks.hyper) > 0,
NumberPad: numberPad,
}
window.child.Handle (tomo.EventKeyUp {
Key: key,
Modifiers: modifiers,
})
}
func (window *Window) handleButtonPress (
connection *xgbutil.XUtil,
event xevent.ButtonPressEvent,
) {
if window.child == nil { return }
buttonEvent := *event.ButtonPressEvent
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 {
sum := scrollSum { }
sum.add(buttonEvent.Detail)
window.compressScrollSum(buttonEvent, &sum)
window.child.Handle (tomo.EventScroll {
X: int(buttonEvent.EventX),
Y: int(buttonEvent.EventY),
ScrollX: sum.x,
ScrollY: sum.y,
})
} else {
window.child.Handle (tomo.EventMouseDown {
Button: tomo.Button(buttonEvent.Detail),
X: int(buttonEvent.EventX),
Y: int(buttonEvent.EventY),
})
}
}
func (window *Window) handleButtonRelease (
connection *xgbutil.XUtil,
event xevent.ButtonReleaseEvent,
) {
buttonEvent := *event.ButtonReleaseEvent
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { return }
window.child.Handle (tomo.EventMouseUp {
Button: tomo.Button(buttonEvent.Detail),
X: int(buttonEvent.EventX),
Y: int(buttonEvent.EventY),
})
}
func (window *Window) handleMotionNotify (
connection *xgbutil.XUtil,
event xevent.MotionNotifyEvent,
) {
motionEvent := window.compressMotionNotify(*event.MotionNotifyEvent)
window.child.Handle (tomo.EventMouseMove {
X: int(motionEvent.EventX),
Y: int(motionEvent.EventY),
})
}
func (window *Window) compressConfigureNotify (
firstEvent xproto.ConfigureNotifyEvent,
) (
lastEvent xproto.ConfigureNotifyEvent,
) {
window.backend.connection.Sync()
xevent.Read(window.backend.connection, false)
lastEvent = firstEvent
for index, untypedEvent := range xevent.Peek(window.backend.connection) {
if untypedEvent.Err != nil { continue }
typedEvent, ok := untypedEvent.Event.(xproto.ConfigureNotifyEvent)
if !ok { continue }
if firstEvent.Event == typedEvent.Event &&
firstEvent.Window == typedEvent.Window {
lastEvent = typedEvent
defer func (index int) {
xevent.DequeueAt(window.backend.connection, index)
} (index)
}
}
return
}
func (window *Window) compressScrollSum (
firstEvent xproto.ButtonPressEvent,
sum *scrollSum,
) {
window.backend.connection.Sync()
xevent.Read(window.backend.connection, false)
for index, untypedEvent := range xevent.Peek(window.backend.connection) {
if untypedEvent.Err != nil { continue }
typedEvent, ok := untypedEvent.Event.(xproto.ButtonPressEvent)
if !ok { continue }
if firstEvent.Event == typedEvent.Event &&
typedEvent.Detail >= 4 &&
typedEvent.Detail <= 7 {
sum.add(typedEvent.Detail)
defer func (index int) {
xevent.DequeueAt(window.backend.connection, index)
} (index)
}
}
return
}
func (window *Window) compressMotionNotify (
firstEvent xproto.MotionNotifyEvent,
) (
lastEvent xproto.MotionNotifyEvent,
) {
window.backend.connection.Sync()
xevent.Read(window.backend.connection, false)
lastEvent = firstEvent
for index, untypedEvent := range xevent.Peek(window.backend.connection) {
if untypedEvent.Err != nil { continue }
typedEvent, ok := untypedEvent.Event.(xproto.MotionNotifyEvent)
if !ok { continue }
if firstEvent.Event == typedEvent.Event &&
typedEvent.Detail >= 4 &&
typedEvent.Detail <= 7 {
lastEvent = typedEvent
defer func (index int) {
xevent.DequeueAt(window.backend.connection, index)
} (index)
}
}
return
}