robust-parenting #12

Merged
sashakoshka merged 17 commits from robust-parenting into main 2023-03-15 22:34:08 -06:00
3 changed files with 62 additions and 68 deletions
Showing only changes of commit 14ad35d85c - Show all commits

View File

@ -14,7 +14,7 @@ type scrollSum struct {
const scrollDistance = 16
func (sum *scrollSum) add (button xproto.Button, window *Window, state uint16) {
func (sum *scrollSum) add (button xproto.Button, window *window, state uint16) {
shift :=
(state & xproto.ModMaskShift) > 0 ||
(state & window.backend.modifierMasks.shiftLock) > 0
@ -44,7 +44,7 @@ func (sum *scrollSum) add (button xproto.Button, window *Window, state uint16) {
}
func (window *Window) handleExpose (
func (window *window) handleExpose (
connection *xgbutil.XUtil,
event xevent.ExposeEvent,
) {
@ -52,7 +52,7 @@ func (window *Window) handleExpose (
window.pushRegion(region)
}
func (window *Window) handleConfigureNotify (
func (window *window) handleConfigureNotify (
connection *xgbutil.XUtil,
event xevent.ConfigureNotifyEvent,
) {
@ -81,7 +81,7 @@ func (window *Window) handleConfigureNotify (
}
}
func (window *Window) exposeEventFollows (event xproto.ConfigureNotifyEvent) (found bool) {
func (window *window) exposeEventFollows (event xproto.ConfigureNotifyEvent) (found bool) {
nextEvents := xevent.Peek(window.backend.connection)
if len(nextEvents) > 0 {
untypedEvent := nextEvents[0]
@ -97,7 +97,7 @@ func (window *Window) exposeEventFollows (event xproto.ConfigureNotifyEvent) (fo
return false
}
func (window *Window) modifiersFromState (
func (window *window) modifiersFromState (
state uint16,
) (
modifiers input.Modifiers,
@ -114,7 +114,7 @@ func (window *Window) modifiersFromState (
}
}
func (window *Window) handleKeyPress (
func (window *window) handleKeyPress (
connection *xgbutil.XUtil,
event xevent.KeyPressEvent,
) {
@ -141,7 +141,7 @@ func (window *Window) handleKeyPress (
}
}
func (window *Window) handleKeyRelease (
func (window *window) handleKeyRelease (
connection *xgbutil.XUtil,
event xevent.KeyReleaseEvent,
) {
@ -175,23 +175,25 @@ func (window *Window) handleKeyRelease (
}
}
func (window *Window) handleButtonPress (
func (window *window) handleButtonPress (
connection *xgbutil.XUtil,
event xevent.ButtonPressEvent,
) {
if window.child == nil { return }
if child, ok := window.child.(elements.MouseTarget); ok {
buttonEvent := *event.ButtonPressEvent
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 {
buttonEvent := *event.ButtonPressEvent
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 {
if child, ok := window.child.(elements.ScrollTarget); ok {
sum := scrollSum { }
sum.add(buttonEvent.Detail, window, buttonEvent.State)
window.compressScrollSum(buttonEvent, &sum)
child.HandleMouseScroll (
child.HandleScroll (
int(buttonEvent.EventX),
int(buttonEvent.EventY),
float64(sum.x), float64(sum.y))
} else {
}
} else {
if child, ok := window.child.(elements.MouseTarget); ok {
child.HandleMouseDown (
int(buttonEvent.EventX),
int(buttonEvent.EventY),
@ -201,7 +203,7 @@ func (window *Window) handleButtonPress (
}
func (window *Window) handleButtonRelease (
func (window *window) handleButtonRelease (
connection *xgbutil.XUtil,
event xevent.ButtonReleaseEvent,
) {
@ -217,21 +219,21 @@ func (window *Window) handleButtonRelease (
}
}
func (window *Window) handleMotionNotify (
func (window *window) handleMotionNotify (
connection *xgbutil.XUtil,
event xevent.MotionNotifyEvent,
) {
if window.child == nil { return }
if child, ok := window.child.(elements.MouseTarget); ok {
if child, ok := window.child.(elements.MotionTarget); ok {
motionEvent := window.compressMotionNotify(*event.MotionNotifyEvent)
child.HandleMouseMove (
child.HandleMotion (
int(motionEvent.EventX),
int(motionEvent.EventY))
}
}
func (window *Window) compressExpose (
func (window *window) compressExpose (
firstEvent xproto.ExposeEvent,
) (
lastEvent xproto.ExposeEvent,
@ -268,7 +270,7 @@ func (window *Window) compressExpose (
return
}
func (window *Window) compressConfigureNotify (
func (window *window) compressConfigureNotify (
firstEvent xproto.ConfigureNotifyEvent,
) (
lastEvent xproto.ConfigureNotifyEvent,
@ -296,7 +298,7 @@ func (window *Window) compressConfigureNotify (
return
}
func (window *Window) compressScrollSum (
func (window *window) compressScrollSum (
firstEvent xproto.ButtonPressEvent,
sum *scrollSum,
) {
@ -323,7 +325,7 @@ func (window *Window) compressScrollSum (
return
}
func (window *Window) compressMotionNotify (
func (window *window) compressMotionNotify (
firstEvent xproto.MotionNotifyEvent,
) (
lastEvent xproto.MotionNotifyEvent,

View File

@ -14,7 +14,7 @@ import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/elements"
// import "runtime/debug"
type Window struct {
type window struct {
backend *Backend
xWindow *xwindow.Window
xCanvas *xgraphics.Image
@ -40,7 +40,7 @@ func (backend *Backend) NewWindow (
) {
if backend == nil { panic("nil backend") }
window := &Window { backend: backend }
window := &window { backend: backend }
window.xWindow, err = xwindow.Generate(backend.connection)
if err != nil { return }
@ -90,18 +90,15 @@ func (backend *Backend) NewWindow (
return
}
func (window *Window) Adopt (child elements.Element) {
func (window *window) NotifyMinimumSizeChange (child elements.Element) {
window.childMinimumSizeChangeCallback(child.MinimumSize())
}
func (window *window) Adopt (child elements.Element) {
// disown previous child
if window.child != nil {
window.child.OnDamage(nil)
window.child.OnMinimumSizeChange(nil)
}
if previousChild, ok := window.child.(elements.Focusable); ok {
previousChild.OnFocusRequest(nil)
previousChild.OnFocusMotionRequest(nil)
if previousChild.Focused() {
previousChild.HandleUnfocus()
}
window.child.SetParent(nil)
window.child.DrawTo(nil, image.Rectangle { }, nil)
}
// adopt new child
@ -112,15 +109,7 @@ func (window *Window) Adopt (child elements.Element) {
if newChild, ok := child.(elements.Configurable); ok {
newChild.SetConfig(window.config)
}
if newChild, ok := child.(elements.Focusable); ok {
newChild.OnFocusRequest(window.childSelectionRequestCallback)
}
if child != nil {
child.OnDamage(window.childDrawCallback)
child.OnMinimumSizeChange (func () {
window.childMinimumSizeChangeCallback (
child.MinimumSize())
})
if !window.childMinimumSizeChangeCallback(child.MinimumSize()) {
window.resizeChildToFit()
window.redrawChildEntirely()
@ -128,19 +117,19 @@ func (window *Window) Adopt (child elements.Element) {
}
}
func (window *Window) Child () (child elements.Element) {
func (window *window) Child () (child elements.Element) {
child = window.child
return
}
func (window *Window) SetTitle (title string) {
func (window *window) SetTitle (title string) {
ewmh.WmNameSet (
window.backend.connection,
window.xWindow.Id,
title)
}
func (window *Window) SetIcon (sizes []image.Image) {
func (window *window) SetIcon (sizes []image.Image) {
wmIcons := []ewmh.WmIcon { }
for _, icon := range sizes {
@ -179,7 +168,7 @@ func (window *Window) SetIcon (sizes []image.Image) {
wmIcons)
}
func (window *Window) Show () {
func (window *window) Show () {
if window.child == nil {
window.xCanvas.For (func (x, y int) xgraphics.BGRA {
return xgraphics.BGRA { }
@ -191,35 +180,35 @@ func (window *Window) Show () {
window.xWindow.Map()
}
func (window *Window) Hide () {
func (window *window) Hide () {
window.xWindow.Unmap()
}
func (window *Window) Close () {
func (window *window) Close () {
if window.onClose != nil { window.onClose() }
delete(window.backend.windows, window.xWindow.Id)
window.xWindow.Destroy()
}
func (window *Window) OnClose (callback func ()) {
func (window *window) OnClose (callback func ()) {
window.onClose = callback
}
func (window *Window) SetTheme (theme theme.Theme) {
func (window *window) SetTheme (theme theme.Theme) {
window.theme = theme
if child, ok := window.child.(elements.Themeable); ok {
child.SetTheme(theme)
}
}
func (window *Window) SetConfig (config config.Config) {
func (window *window) SetConfig (config config.Config) {
window.config = config
if child, ok := window.child.(elements.Configurable); ok {
child.SetConfig(config)
}
}
func (window *Window) reallocateCanvas () {
func (window *window) reallocateCanvas () {
window.canvas.Reallocate(window.metrics.width, window.metrics.height)
previousWidth, previousHeight := 0, 0
@ -250,23 +239,28 @@ func (window *Window) reallocateCanvas () {
}
func (window *Window) redrawChildEntirely () {
window.pushRegion(window.paste(window.canvas))
func (window *window) redrawChildEntirely () {
window.paste(window.canvas.Bounds())
window.pushRegion(window.canvas.Bounds())
}
func (window *Window) resizeChildToFit () {
func (window *window) resizeChildToFit () {
window.skipChildDrawCallback = true
window.child.DrawTo(window.canvas, window.canvas.Bounds())
window.child.DrawTo (
window.canvas,
window.canvas.Bounds(),
window.childDrawCallback)
window.skipChildDrawCallback = false
}
func (window *Window) childDrawCallback (region canvas.Canvas) {
func (window *window) childDrawCallback (region image.Rectangle) {
if window.skipChildDrawCallback { return }
window.pushRegion(window.paste(region))
window.paste(region)
window.pushRegion(region)
}
func (window *Window) paste (canvas canvas.Canvas) (updatedRegion image.Rectangle) {
func (window *window) paste (region image.Rectangle) {
canvas := canvas.Cut(window.canvas, region)
data, stride := canvas.Buffer()
bounds := canvas.Bounds().Intersect(window.xCanvas.Bounds())
@ -286,11 +280,9 @@ func (window *Window) paste (canvas canvas.Canvas) (updatedRegion image.Rectangl
dstData[index + 3] = rgba.A
}
}
return bounds
}
func (window *Window) childMinimumSizeChangeCallback (width, height int) (resized bool) {
func (window *window) childMinimumSizeChangeCallback (width, height int) (resized bool) {
icccm.WmNormalHintsSet (
window.backend.connection,
window.xWindow.Id,
@ -312,14 +304,14 @@ func (window *Window) childMinimumSizeChangeCallback (width, height int) (resize
return false
}
func (window *Window) childSelectionRequestCallback () (granted bool) {
func (window *window) childSelectionRequestCallback () (granted bool) {
if _, ok := window.child.(elements.Focusable); ok {
return true
}
return false
}
func (window *Window) childSelectionMotionRequestCallback (
func (window *window) childSelectionMotionRequestCallback (
direction input.KeynavDirection,
) (
granted bool,
@ -333,7 +325,7 @@ func (window *Window) childSelectionMotionRequestCallback (
return true
}
func (window *Window) pushRegion (region image.Rectangle) {
func (window *window) pushRegion (region image.Rectangle) {
if window.xCanvas == nil { panic("whoopsie!!!!!!!!!!!!!!") }
image, ok := window.xCanvas.SubImage(region).(*xgraphics.Image)
if ok {

View File

@ -30,7 +30,7 @@ type Backend struct {
theme theme.Theme
config config.Config
windows map[xproto.Window] *Window
windows map[xproto.Window] *window
open bool
}
@ -38,7 +38,7 @@ type Backend struct {
// NewBackend instantiates an X backend.
func NewBackend () (output tomo.Backend, err error) {
backend := &Backend {
windows: map[xproto.Window] *Window { },
windows: map[xproto.Window] *window { },
doChannel: make(chan func (), 0),
theme: theme.Default { },
config: config.Default { },
@ -79,7 +79,7 @@ func (backend *Backend) Stop () {
if !backend.open { return }
backend.open = false
toClose := []*Window { }
toClose := []*window { }
for _, window := range backend.windows {
toClose = append(toClose, window)
}