From 77ef7554ac33e5a102fffac3b1b3915b9b0d7d2f Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 15 Jan 2023 12:23:13 -0500 Subject: [PATCH] X backend conforms to new API --- backends/x/event.go | 107 ++++++++++++++++++++++--------------------- backends/x/window.go | 27 +++++++---- element.go | 30 +++++++++--- 3 files changed, 97 insertions(+), 67 deletions(-) diff --git a/backends/x/event.go b/backends/x/event.go index 97344a8..a7010d7 100644 --- a/backends/x/event.go +++ b/backends/x/event.go @@ -27,6 +27,8 @@ func (window *Window) handleConfigureNotify ( connection *xgbutil.XUtil, event xevent.ConfigureNotifyEvent, ) { + if window.child == nil { return } + configureEvent := *event.ConfigureNotifyEvent newWidth := int(configureEvent.Width) @@ -66,33 +68,29 @@ func (window *Window) handleKeyPress ( 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 + if key == tomo.KeyTab && modifiers.Alt { + if _, ok := window.child.(tomo.Selectable); ok { + direction := tomo.SelectionDirectionForward + if modifiers.Shift { + direction = tomo.SelectionDirectionBackward } window.advanceSelectionInChild(direction) } - } else { - window.child.Handle(keyDownEvent) + } else if child, ok := window.child.(tomo.KeyboardTarget); ok { + // FIXME: pass correct value for repeated + child.HandleKeyDown(key, modifiers, false) } } -func (window *Window) advanceSelectionInChild (direction int) { - if window.child.Selected() { - if !window.child.AdvanceSelection(direction) { - window.child.Handle(tomo.EventDeselect { }) +func (window *Window) advanceSelectionInChild (direction tomo.SelectionDirection) { + child := window.child.(tomo.Selectable) + if child.Selected() { + if !child.HandleSelection(direction) { + child.HandleDeselection() } } else { - window.child.Handle(tomo.EventSelect { }) + child.HandleSelection(tomo.SelectionDirectionNeutral) } } @@ -115,11 +113,10 @@ func (window *Window) handleKeyRelease ( Hyper: (keyEvent.State & window.backend.modifierMasks.hyper) > 0, NumberPad: numberPad, } - - window.child.Handle (tomo.EventKeyUp { - Key: key, - Modifiers: modifiers, - }) + + if child, ok := window.child.(tomo.KeyboardTarget); ok { + child.HandleKeyUp(key, modifiers) + } } func (window *Window) handleButtonPress ( @@ -128,48 +125,54 @@ func (window *Window) handleButtonPress ( ) { 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), - }) + if child, ok := window.child.(tomo.MouseTarget); ok { + buttonEvent := *event.ButtonPressEvent + if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { + sum := scrollSum { } + sum.add(buttonEvent.Detail) + window.compressScrollSum(buttonEvent, &sum) + child.HandleScroll ( + int(buttonEvent.EventX), + int(buttonEvent.EventY), + float64(sum.x), float64(sum.y)) + } else { + child.HandleMouseDown ( + int(buttonEvent.EventX), + int(buttonEvent.EventY), + tomo.Button(buttonEvent.Detail)) + } } + } 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), - }) + if window.child == nil { return } + + if child, ok := window.child.(tomo.MouseTarget); ok { + buttonEvent := *event.ButtonReleaseEvent + if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { return } + child.HandleMouseUp ( + int(buttonEvent.EventX), + int(buttonEvent.EventY), + tomo.Button(buttonEvent.Detail)) + } } 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), - }) + if window.child == nil { return } + + if child, ok := window.child.(tomo.MouseTarget); ok { + motionEvent := window.compressMotionNotify(*event.MotionNotifyEvent) + child.HandleMouseMove ( + int(motionEvent.EventX), + int(motionEvent.EventY)) + } } diff --git a/backends/x/window.go b/backends/x/window.go index b2f3f7b..aeffb03 100644 --- a/backends/x/window.go +++ b/backends/x/window.go @@ -78,7 +78,11 @@ func (backend *Backend) NewWindow ( func (window *Window) Adopt (child tomo.Element) { if window.child != nil { child.SetParentHooks (tomo.ParentHooks { }) - if child.Selected() { child.Handle(tomo.EventDeselect { }) } + if previousChild, ok := window.child.(tomo.Selectable); ok { + if previousChild.Selected() { + previousChild.HandleDeselection() + } + } } window.child = child if child != nil { @@ -88,7 +92,6 @@ func (window *Window) Adopt (child tomo.Element) { SelectionRequest: window.childSelectionRequestCallback, }) - if child.Selectable() { child.Handle(tomo.EventSelect { }) } window.resizeChildToFit() } window.childMinimumSizeChangeCallback(child.MinimumSize()) @@ -199,12 +202,18 @@ func (window *Window) redrawChildEntirely () { func (window *Window) resizeChildToFit () { window.skipChildDrawCallback = true - window.child.Handle(tomo.EventResize { - Width: window.metrics.width, - Height: window.metrics.height, - }) + if child, ok := window.child.(tomo.Expanding); ok { + minimumHeight := child.MinimumHeightFor(window.metrics.width) + _, minimumWidth := child.MinimumSize() + window.childMinimumSizeChangeCallback ( + minimumWidth, minimumHeight) + } else { + window.child.Resize ( + window.metrics.width, + window.metrics.height) + window.redrawChildEntirely() + } window.skipChildDrawCallback = false - window.redrawChildEntirely() } func (window *Window) childDrawCallback (region tomo.Canvas) { @@ -246,7 +255,9 @@ func (window *Window) childMinimumSizeChangeCallback (width, height int) { } func (window *Window) childSelectionRequestCallback () (granted bool) { - window.child.Handle(tomo.EventSelect { }) + if child, ok := window.child.(tomo.Selectable); ok { + child.HandleSelection(tomo.SelectionDirectionNeutral) + } return true } diff --git a/element.go b/element.go index 9aedcc6..15a5312 100644 --- a/element.go +++ b/element.go @@ -53,17 +53,21 @@ type Element interface { // on it for the first time when sent an EventResize event. Canvas - // SetParentHooks gives the element callbacks that let it send - // information to its parent element without it knowing anything about - // the parent element or containing any reference to it. When a parent - // element adopts a child element, it must set these callbacks. - SetParentHooks (callbacks ParentHooks) - // MinimumSize specifies the minimum amount of pixels this element's // width and height may be set to. If the element is given a resize // event with dimensions smaller than this, it will use its minimum // instead of the offending dimension(s). MinimumSize () (width, height int) + + // Resize resizes the element. This should only be called by the + // element's parent. + Resize (width, height int) + + // SetParentHooks gives the element callbacks that let it send + // information to its parent element without it knowing anything about + // the parent element or containing any reference to it. When a parent + // element adopts a child element, it must set these callbacks. + SetParentHooks (callbacks ParentHooks) } // SelectionDirection represents a keyboard navigation direction. @@ -110,7 +114,7 @@ type KeyboardTarget interface { // HandleKeyUp is called when a key is released while this element has // keyboard focus. - HandleKeyUp (key Key) + HandleKeyUp (key Key, modifiers Modifiers) } // MouseTarget represents an element that can receive mouse events. @@ -137,3 +141,15 @@ type MouseTarget interface { // direction of the scroll event are passed as deltaX and deltaY. HandleScroll (x, y int, deltaX, deltaY float64) } + +// Expanding represents an element who's minimum height can change in response +// to a change in its width. +type Expanding interface { + Element + + // HeightForWidth returns what the element's minimum height would be if + // resized to the specified width. This does not actually alter the + // state of the element in any way, but it may perform significant work, + // so it should be used sparingly. + MinimumHeightFor (width int) (height int) +}