X backend conforms to new API

This commit is contained in:
Sasha Koshka 2023-01-15 12:23:13 -05:00
parent 8cfb8eeaef
commit 77ef7554ac
3 changed files with 97 additions and 67 deletions

View File

@ -27,6 +27,8 @@ func (window *Window) handleConfigureNotify (
connection *xgbutil.XUtil, connection *xgbutil.XUtil,
event xevent.ConfigureNotifyEvent, event xevent.ConfigureNotifyEvent,
) { ) {
if window.child == nil { return }
configureEvent := *event.ConfigureNotifyEvent configureEvent := *event.ConfigureNotifyEvent
newWidth := int(configureEvent.Width) newWidth := int(configureEvent.Width)
@ -66,33 +68,29 @@ func (window *Window) handleKeyPress (
NumberPad: numberPad, NumberPad: numberPad,
} }
keyDownEvent := tomo.EventKeyDown { if key == tomo.KeyTab && modifiers.Alt {
Key: key, if _, ok := window.child.(tomo.Selectable); ok {
Modifiers: modifiers, direction := tomo.SelectionDirectionForward
Repeated: false, // FIXME: return correct value here if modifiers.Shift {
} direction = tomo.SelectionDirectionBackward
if keyDownEvent.Key == tomo.KeyTab && keyDownEvent.Modifiers.Alt {
if window.child.Selectable() {
direction := 1
if keyDownEvent.Modifiers.Shift {
direction = -1
} }
window.advanceSelectionInChild(direction) window.advanceSelectionInChild(direction)
} }
} else { } else if child, ok := window.child.(tomo.KeyboardTarget); ok {
window.child.Handle(keyDownEvent) // FIXME: pass correct value for repeated
child.HandleKeyDown(key, modifiers, false)
} }
} }
func (window *Window) advanceSelectionInChild (direction int) { func (window *Window) advanceSelectionInChild (direction tomo.SelectionDirection) {
if window.child.Selected() { child := window.child.(tomo.Selectable)
if !window.child.AdvanceSelection(direction) { if child.Selected() {
window.child.Handle(tomo.EventDeselect { }) if !child.HandleSelection(direction) {
child.HandleDeselection()
} }
} else { } 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, Hyper: (keyEvent.State & window.backend.modifierMasks.hyper) > 0,
NumberPad: numberPad, NumberPad: numberPad,
} }
window.child.Handle (tomo.EventKeyUp { if child, ok := window.child.(tomo.KeyboardTarget); ok {
Key: key, child.HandleKeyUp(key, modifiers)
Modifiers: modifiers, }
})
} }
func (window *Window) handleButtonPress ( func (window *Window) handleButtonPress (
@ -128,48 +125,54 @@ func (window *Window) handleButtonPress (
) { ) {
if window.child == nil { return } if window.child == nil { return }
buttonEvent := *event.ButtonPressEvent if child, ok := window.child.(tomo.MouseTarget); ok {
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { buttonEvent := *event.ButtonPressEvent
sum := scrollSum { } if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 {
sum.add(buttonEvent.Detail) sum := scrollSum { }
window.compressScrollSum(buttonEvent, &sum) sum.add(buttonEvent.Detail)
window.child.Handle (tomo.EventScroll { window.compressScrollSum(buttonEvent, &sum)
X: int(buttonEvent.EventX), child.HandleScroll (
Y: int(buttonEvent.EventY), int(buttonEvent.EventX),
ScrollX: sum.x, int(buttonEvent.EventY),
ScrollY: sum.y, float64(sum.x), float64(sum.y))
}) } else {
} else { child.HandleMouseDown (
window.child.Handle (tomo.EventMouseDown { int(buttonEvent.EventX),
Button: tomo.Button(buttonEvent.Detail), int(buttonEvent.EventY),
X: int(buttonEvent.EventX), tomo.Button(buttonEvent.Detail))
Y: int(buttonEvent.EventY), }
})
} }
} }
func (window *Window) handleButtonRelease ( func (window *Window) handleButtonRelease (
connection *xgbutil.XUtil, connection *xgbutil.XUtil,
event xevent.ButtonReleaseEvent, event xevent.ButtonReleaseEvent,
) { ) {
buttonEvent := *event.ButtonReleaseEvent if window.child == nil { return }
if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { return }
window.child.Handle (tomo.EventMouseUp { if child, ok := window.child.(tomo.MouseTarget); ok {
Button: tomo.Button(buttonEvent.Detail), buttonEvent := *event.ButtonReleaseEvent
X: int(buttonEvent.EventX), if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { return }
Y: int(buttonEvent.EventY), child.HandleMouseUp (
}) int(buttonEvent.EventX),
int(buttonEvent.EventY),
tomo.Button(buttonEvent.Detail))
}
} }
func (window *Window) handleMotionNotify ( func (window *Window) handleMotionNotify (
connection *xgbutil.XUtil, connection *xgbutil.XUtil,
event xevent.MotionNotifyEvent, event xevent.MotionNotifyEvent,
) { ) {
motionEvent := window.compressMotionNotify(*event.MotionNotifyEvent) if window.child == nil { return }
window.child.Handle (tomo.EventMouseMove {
X: int(motionEvent.EventX), if child, ok := window.child.(tomo.MouseTarget); ok {
Y: int(motionEvent.EventY), motionEvent := window.compressMotionNotify(*event.MotionNotifyEvent)
}) child.HandleMouseMove (
int(motionEvent.EventX),
int(motionEvent.EventY))
}
} }

View File

@ -78,7 +78,11 @@ func (backend *Backend) NewWindow (
func (window *Window) Adopt (child tomo.Element) { func (window *Window) Adopt (child tomo.Element) {
if window.child != nil { if window.child != nil {
child.SetParentHooks (tomo.ParentHooks { }) 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 window.child = child
if child != nil { if child != nil {
@ -88,7 +92,6 @@ func (window *Window) Adopt (child tomo.Element) {
SelectionRequest: window.childSelectionRequestCallback, SelectionRequest: window.childSelectionRequestCallback,
}) })
if child.Selectable() { child.Handle(tomo.EventSelect { }) }
window.resizeChildToFit() window.resizeChildToFit()
} }
window.childMinimumSizeChangeCallback(child.MinimumSize()) window.childMinimumSizeChangeCallback(child.MinimumSize())
@ -199,12 +202,18 @@ func (window *Window) redrawChildEntirely () {
func (window *Window) resizeChildToFit () { func (window *Window) resizeChildToFit () {
window.skipChildDrawCallback = true window.skipChildDrawCallback = true
window.child.Handle(tomo.EventResize { if child, ok := window.child.(tomo.Expanding); ok {
Width: window.metrics.width, minimumHeight := child.MinimumHeightFor(window.metrics.width)
Height: window.metrics.height, _, minimumWidth := child.MinimumSize()
}) window.childMinimumSizeChangeCallback (
minimumWidth, minimumHeight)
} else {
window.child.Resize (
window.metrics.width,
window.metrics.height)
window.redrawChildEntirely()
}
window.skipChildDrawCallback = false window.skipChildDrawCallback = false
window.redrawChildEntirely()
} }
func (window *Window) childDrawCallback (region tomo.Canvas) { func (window *Window) childDrawCallback (region tomo.Canvas) {
@ -246,7 +255,9 @@ func (window *Window) childMinimumSizeChangeCallback (width, height int) {
} }
func (window *Window) childSelectionRequestCallback () (granted bool) { 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 return true
} }

View File

@ -53,17 +53,21 @@ type Element interface {
// on it for the first time when sent an EventResize event. // on it for the first time when sent an EventResize event.
Canvas 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 // MinimumSize specifies the minimum amount of pixels this element's
// width and height may be set to. If the element is given a resize // 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 // event with dimensions smaller than this, it will use its minimum
// instead of the offending dimension(s). // instead of the offending dimension(s).
MinimumSize () (width, height int) 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. // 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 // HandleKeyUp is called when a key is released while this element has
// keyboard focus. // keyboard focus.
HandleKeyUp (key Key) HandleKeyUp (key Key, modifiers Modifiers)
} }
// MouseTarget represents an element that can receive mouse events. // 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. // direction of the scroll event are passed as deltaX and deltaY.
HandleScroll (x, y int, deltaX, deltaY float64) 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)
}