259 lines
6.6 KiB
Go
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
|
|
}
|