diff --git a/backends/x/event.go b/backends/x/event.go index 5f6b773..d5da4ad 100644 --- a/backends/x/event.go +++ b/backends/x/event.go @@ -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, diff --git a/backends/x/window.go b/backends/x/window.go index 67d352a..ecd4e86 100644 --- a/backends/x/window.go +++ b/backends/x/window.go @@ -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 { diff --git a/backends/x/x.go b/backends/x/x.go index eefd914..d72ce1f 100644 --- a/backends/x/x.go +++ b/backends/x/x.go @@ -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) }