diff --git a/backends/x/event.go b/backends/x/event.go index c099268..ed701e5 100644 --- a/backends/x/event.go +++ b/backends/x/event.go @@ -189,6 +189,7 @@ func (window *window) handleButtonPress ( point := image.Pt(int(buttonEvent.EventX), int(buttonEvent.EventY)) insideWindow := point.In(window.canvas.Bounds()) scrolling := buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 + modifiers := window.modifiersFromState(buttonEvent.State) if !insideWindow && window.shy && !scrolling { window.Close() @@ -200,8 +201,8 @@ func (window *window) handleButtonPress ( sum.add(buttonEvent.Detail, window, buttonEvent.State) window.compressScrollSum(buttonEvent, &sum) child.HandleScroll ( - point.X, point.Y, - float64(sum.x), float64(sum.y)) + point, float64(sum.x), float64(sum.y), + modifiers) } } } else { @@ -209,14 +210,13 @@ func (window *window) handleButtonPress ( window.system.drags[buttonEvent.Detail] = underneath if child, ok := underneath.element.(tomo.MouseTarget); ok { child.HandleMouseDown ( - point.X, point.Y, - input.Button(buttonEvent.Detail)) + point, input.Button(buttonEvent.Detail), + modifiers) } callback := func (container tomo.MouseTargetContainer, child tomo.Element) { container.HandleChildMouseDown ( - point.X, point.Y, - input.Button(buttonEvent.Detail), - child) + point, input.Button(buttonEvent.Detail), + modifiers, child) } underneath.forMouseTargetContainers(callback) } @@ -230,20 +230,25 @@ func (window *window) handleButtonRelease ( ) { buttonEvent := *event.ButtonReleaseEvent if buttonEvent.Detail >= 4 && buttonEvent.Detail <= 7 { return } + modifiers := window.modifiersFromState(buttonEvent.State) dragging := window.system.drags[buttonEvent.Detail] + if dragging != nil { if child, ok := dragging.element.(tomo.MouseTarget); ok { child.HandleMouseUp ( - int(buttonEvent.EventX), - int(buttonEvent.EventY), - input.Button(buttonEvent.Detail)) + image.Pt ( + int(buttonEvent.EventX), + int(buttonEvent.EventY)), + input.Button(buttonEvent.Detail), + modifiers) } callback := func (container tomo.MouseTargetContainer, child tomo.Element) { container.HandleChildMouseUp ( - int(buttonEvent.EventX), - int(buttonEvent.EventY), - input.Button(buttonEvent.Detail), - child) + image.Pt ( + int(buttonEvent.EventX), + int(buttonEvent.EventY)), + input.Button(buttonEvent.Detail), + modifiers, child) } dragging.forMouseTargetContainers(callback) } @@ -263,7 +268,7 @@ func (window *window) handleMotionNotify ( for _, child := range window.system.drags { if child == nil { continue } if child, ok := child.element.(tomo.MotionTarget); ok { - child.HandleMotion(x, y) + child.HandleMotion(image.Pt(x, y)) handled = true } } @@ -271,7 +276,7 @@ func (window *window) handleMotionNotify ( if !handled { child := window.system.childAt(image.Pt(x, y)) if child, ok := child.element.(tomo.MotionTarget); ok { - child.HandleMotion(x, y) + child.HandleMotion(image.Pt(x, y)) } } diff --git a/element.go b/element.go index cad0a80..a92a4f7 100644 --- a/element.go +++ b/element.go @@ -99,11 +99,17 @@ type MouseTarget interface { // HandleMouseDown is called when a mouse button is pressed down on this // element. - HandleMouseDown (x, y int, button input.Button) + HandleMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers) // HandleMouseUp is called when a mouse button is released that was // originally pressed down on this element. - HandleMouseUp (x, y int, button input.Button) + HandleMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers) } // MouseTargetContainer represents an element that wants to know when one @@ -115,11 +121,19 @@ type MouseTargetContainer interface { // HandleMouseDown is called when a mouse button is pressed down on a // child element. - HandleChildMouseDown (x, y int, button input.Button, child Element) + HandleChildMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers, + child Element) // HandleMouseUp is called when a mouse button is released that was // originally pressed down on a child element. - HandleChildMouseUp (x, y int, button input.Button, child Element) + HandleChildMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers, + child Element) } // MotionTarget represents an element that can receive mouse motion events. @@ -129,7 +143,7 @@ type MotionTarget interface { // HandleMotion is called when the mouse is moved over this element, // or the mouse is moving while being held down and originally pressed // down on this element. - HandleMotion (x, y int) + HandleMotion (position image.Point) } // ScrollTarget represents an element that can receive mouse scroll events. @@ -138,7 +152,10 @@ type ScrollTarget interface { // HandleScroll is called when the mouse is scrolled. The X and Y // direction of the scroll event are passed as deltaX and deltaY. - HandleScroll (x, y int, deltaX, deltaY float64) + HandleScroll ( + position image.Point, + deltaX, deltaY float64, + modifiers input.Modifiers) } // Flexible represents an element who's preferred minimum height can change in @@ -158,7 +175,8 @@ type Flexible interface { // minimum size that the element may be resized to. // // It is important to note that if a parent container checks for - // flexible chilren, it itself will likely need to be flexible. + // flexible chilren, it itself will likely need to be either scrollable + // or flexible. FlexibleHeightFor (width int) int } diff --git a/elements/button.go b/elements/button.go index 36552d9..4968843 100644 --- a/elements/button.go +++ b/elements/button.go @@ -177,7 +177,11 @@ func (element *Button) HandleFocusChange () { element.entity.Invalidate() } -func (element *Button) HandleMouseDown (x, y int, button input.Button) { +func (element *Button) HandleMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if !element.Enabled() { return } element.Focus() if button != input.ButtonLeft { return } @@ -185,10 +189,14 @@ func (element *Button) HandleMouseDown (x, y int, button input.Button) { element.entity.Invalidate() } -func (element *Button) HandleMouseUp (x, y int, button input.Button) { +func (element *Button) HandleMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if button != input.ButtonLeft { return } element.pressed = false - within := image.Point { x, y }.In(element.entity.Bounds()) + within := position.In(element.entity.Bounds()) if element.Enabled() && within && element.onClick != nil { element.onClick() } diff --git a/elements/checkbox.go b/elements/checkbox.go index 9ae8295..10a5124 100644 --- a/elements/checkbox.go +++ b/elements/checkbox.go @@ -130,18 +130,26 @@ func (element *Checkbox) HandleFocusChange () { element.entity.Invalidate() } -func (element *Checkbox) HandleMouseDown (x, y int, button input.Button) { +func (element *Checkbox) HandleMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if !element.Enabled() { return } element.Focus() element.pressed = true element.entity.Invalidate() } -func (element *Checkbox) HandleMouseUp (x, y int, button input.Button) { +func (element *Checkbox) HandleMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if button != input.ButtonLeft || !element.pressed { return } element.pressed = false - within := image.Point { x, y }.In(element.entity.Bounds()) + within := position.In(element.entity.Bounds()) if within { element.checked = !element.checked } diff --git a/elements/directory.go b/elements/directory.go index 6859d59..f1b19b7 100644 --- a/elements/directory.go +++ b/elements/directory.go @@ -124,13 +124,26 @@ func (element *Directory) Layout () { } } -func (element *Directory) HandleMouseDown (x, y int, button input.Button) { +func (element *Directory) HandleMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { element.selectNone() } -func (element *Directory) HandleMouseUp (x, y int, button input.Button) { } +func (element *Directory) HandleMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { } -func (element *Directory) HandleChildMouseDown (x, y int, button input.Button, child tomo.Element) { +func (element *Directory) HandleChildMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers, + child tomo.Element, +) { element.selectNone() if child, ok := child.(tomo.Selectable); ok { index := element.entity.IndexOf(child) @@ -138,7 +151,12 @@ func (element *Directory) HandleChildMouseDown (x, y int, button input.Button, c } } -func (element *Directory) HandleChildMouseUp (int, int, input.Button, tomo.Element) { } +func (element *Directory) HandleChildMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers, + child tomo.Element, +) { } func (element *Directory) HandleChildFlexibleHeightChange (child tomo.Flexible) { element.updateMinimumSize() diff --git a/elements/file.go b/elements/file.go index 6d5835c..7504944 100644 --- a/elements/file.go +++ b/elements/file.go @@ -125,7 +125,7 @@ func (element *File) HandleKeyDown (key input.Key, modifiers input.Modifiers) { } } -func (element *File) HandleKeyUp(key input.Key, modifiers input.Modifiers) { +func (element *File) HandleKeyUp (key input.Key, modifiers input.Modifiers) { if key == input.KeyEnter && element.pressed { element.pressed = false if !element.Enabled() { return } @@ -165,7 +165,11 @@ func (element *File) SetEnabled (enabled bool) { element.entity.Invalidate() } -func (element *File) HandleMouseDown (x, y int, button input.Button) { +func (element *File) HandleMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if !element.Enabled() { return } if !element.entity.Focused() { element.Focus() } if button != input.ButtonLeft { return } @@ -173,10 +177,14 @@ func (element *File) HandleMouseDown (x, y int, button input.Button) { element.entity.Invalidate() } -func (element *File) HandleMouseUp (x, y int, button input.Button) { +func (element *File) HandleMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if button != input.ButtonLeft { return } element.pressed = false - within := image.Point { x, y }.In(element.entity.Bounds()) + within := position.In(element.entity.Bounds()) if time.Since(element.lastClick) < element.config.DoubleClickDelay() { if element.Enabled() && within && element.onChoose != nil { element.onChoose() diff --git a/elements/list.go b/elements/list.go index 9f3079e..5c631d3 100644 --- a/elements/list.go +++ b/elements/list.go @@ -87,7 +87,12 @@ func (element *List) Layout () { } } -func (element *List) HandleChildMouseDown (x, y int, button input.Button, child tomo.Element) { +func (element *List) HandleChildMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers, + child tomo.Element, +) { if child, ok := child.(tomo.Selectable); ok { index := element.entity.IndexOf(child) if element.selected == index { return } @@ -99,7 +104,12 @@ func (element *List) HandleChildMouseDown (x, y int, button input.Button, child } } -func (element *List) HandleChildMouseUp (int, int, input.Button, tomo.Element) { } +func (element *List) HandleChildMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers, + child tomo.Element, +) { } func (element *List) HandleChildFlexibleHeightChange (child tomo.Flexible) { element.updateMinimumSize() diff --git a/elements/scroll.go b/elements/scroll.go index 6f0de70..20b18b0 100644 --- a/elements/scroll.go +++ b/elements/scroll.go @@ -2,7 +2,7 @@ package elements import "image" import "git.tebibyte.media/sashakoshka/tomo" -// import "git.tebibyte.media/sashakoshka/tomo/input" +import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/default/theme" import "git.tebibyte.media/sashakoshka/tomo/default/config" @@ -179,8 +179,9 @@ func (element *Scroll) HandleChildScrollBoundsChange (tomo.Scrollable) { } func (element *Scroll) HandleScroll ( - x, y int, + position image.Point, deltaX, deltaY float64, + modifiers input.Modifiers, ) { horizontal, vertical := element.child.ScrollAxes() if !horizontal { deltaX = 0 } diff --git a/elements/scrollbar.go b/elements/scrollbar.go index bded941..2dbadfe 100644 --- a/elements/scrollbar.go +++ b/elements/scrollbar.go @@ -82,18 +82,21 @@ func (element *ScrollBar) Draw (destination canvas.Canvas) { element.bar) } -func (element *ScrollBar) HandleMouseDown (x, y int, button input.Button) { +func (element *ScrollBar) HandleMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { velocity := element.config.ScrollVelocity() - point := image.Pt(x, y) - if point.In(element.bar) { + if position.In(element.bar) { // the mouse is pressed down within the bar's handle element.dragging = true element.entity.Invalidate() element.dragOffset = - point.Sub(element.bar.Min). + position.Sub(element.bar.Min). Add(element.entity.Bounds().Min) - element.dragTo(point) + element.dragTo(position) } else { // the mouse is pressed down within the bar's gutter switch button { @@ -102,7 +105,7 @@ func (element *ScrollBar) HandleMouseDown (x, y int, button input.Button) { // the middle of the handle element.dragging = true element.dragOffset = element.fallbackDragOffset() - element.dragTo(point) + element.dragTo(position) case input.ButtonMiddle: // page up/down on middle click @@ -112,7 +115,7 @@ func (element *ScrollBar) HandleMouseDown (x, y int, button input.Button) { } else { viewport = element.viewportBounds.Dx() } - if element.isAfterHandle(point) { + if element.isAfterHandle(position) { element.scrollBy(viewport) } else { element.scrollBy(-viewport) @@ -120,7 +123,7 @@ func (element *ScrollBar) HandleMouseDown (x, y int, button input.Button) { case input.ButtonRight: // inch up/down on right click - if element.isAfterHandle(point) { + if element.isAfterHandle(position) { element.scrollBy(velocity) } else { element.scrollBy(-velocity) @@ -129,20 +132,28 @@ func (element *ScrollBar) HandleMouseDown (x, y int, button input.Button) { } } -func (element *ScrollBar) HandleMouseUp (x, y int, button input.Button) { +func (element *ScrollBar) HandleMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if element.dragging { element.dragging = false element.entity.Invalidate() } } -func (element *ScrollBar) HandleMotion (x, y int) { +func (element *ScrollBar) HandleMotion (position image.Point) { if element.dragging { - element.dragTo(image.Pt(x, y)) + element.dragTo(position) } } -func (element *ScrollBar) HandleScroll (x, y int, deltaX, deltaY float64) { +func (element *ScrollBar) HandleScroll ( + position image.Point, + deltaX, deltaY float64, + modifiers input.Modifiers, +) { if element.vertical { element.scrollBy(int(deltaY)) } else { diff --git a/elements/slider.go b/elements/slider.go index 717cfc4..6369dba 100644 --- a/elements/slider.go +++ b/elements/slider.go @@ -111,12 +111,16 @@ func (element *slider) HandleFocusChange () { element.entity.Invalidate() } -func (element *slider) HandleMouseDown (x, y int, button input.Button) { +func (element *slider) HandleMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if !element.Enabled() { return } element.Focus() if button == input.ButtonLeft { element.dragging = true - element.value = element.valueFor(x, y) + element.value = element.valueFor(position.X, position.Y) if element.onSlide != nil { element.onSlide() } @@ -124,7 +128,11 @@ func (element *slider) HandleMouseDown (x, y int, button input.Button) { } } -func (element *slider) HandleMouseUp (x, y int, button input.Button) { +func (element *slider) HandleMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if button != input.ButtonLeft || !element.dragging { return } element.dragging = false if element.onRelease != nil { @@ -133,10 +141,10 @@ func (element *slider) HandleMouseUp (x, y int, button input.Button) { element.entity.Invalidate() } -func (element *slider) HandleMotion (x, y int) { +func (element *slider) HandleMotion (position image.Point) { if element.dragging { element.dragging = true - element.value = element.valueFor(x, y) + element.value = element.valueFor(position.X, position.Y) if element.onSlide != nil { element.onSlide() } @@ -144,7 +152,11 @@ func (element *slider) HandleMotion (x, y int) { } } -func (element *slider) HandleScroll (x, y int, deltaX, deltaY float64) { } +func (element *slider) HandleScroll ( + position image.Point, + deltaX, deltaY float64, + modifiers input.Modifiers, +) { } func (element *slider) HandleKeyDown (key input.Key, modifiers input.Modifiers) { switch key { diff --git a/elements/switch.go b/elements/switch.go index 70516eb..45a8ef2 100644 --- a/elements/switch.go +++ b/elements/switch.go @@ -101,19 +101,26 @@ func (element *Switch) HandleFocusChange () { element.entity.Invalidate() } -func (element *Switch) HandleMouseDown (x, y int, button input.Button) { +func (element *Switch) HandleMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if !element.Enabled() { return } element.Focus() element.pressed = true element.entity.Invalidate() } -func (element *Switch) HandleMouseUp (x, y int, button input.Button) { +func (element *Switch) HandleMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if button != input.ButtonLeft || !element.pressed { return } element.pressed = false - within := image.Point { x, y }. - In(element.entity.Bounds()) + within := position.In(element.entity.Bounds()) if within { element.checked = !element.checked } diff --git a/elements/textbox.go b/elements/textbox.go index 5f1ce2f..6c20b39 100644 --- a/elements/textbox.go +++ b/elements/textbox.go @@ -143,12 +143,16 @@ func (element *TextBox) HandleFocusChange () { element.entity.Invalidate() } -func (element *TextBox) HandleMouseDown (x, y int, button input.Button) { +func (element *TextBox) HandleMouseDown ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if !element.Enabled() { return } element.Focus() if button == input.ButtonLeft { - runeIndex := element.atPosition(image.Pt(x, y)) + runeIndex := element.atPosition(position) if runeIndex == -1 { return } if time.Since(element.lastClick) < element.config.DoubleClickDelay() { @@ -164,19 +168,19 @@ func (element *TextBox) HandleMouseDown (x, y int, button input.Button) { } } -func (element *TextBox) HandleMotion (x, y int) { +func (element *TextBox) HandleMotion (position image.Point) { if !element.Enabled() { return } switch element.dragging { case 1: - runeIndex := element.atPosition(image.Pt(x, y)) + runeIndex := element.atPosition(position) if runeIndex > -1 { element.dot.End = runeIndex element.entity.Invalidate() } case 2: - runeIndex := element.atPosition(image.Pt(x, y)) + runeIndex := element.atPosition(position) if runeIndex > -1 { if runeIndex < element.dot.Start { element.dot.End = @@ -213,7 +217,11 @@ func (element *TextBox) atPosition (position image.Point) int { fixedutil.Pt(position.Sub(offset).Add(textBoundsMin))) } -func (element *TextBox) HandleMouseUp (x, y int, button input.Button) { +func (element *TextBox) HandleMouseUp ( + position image.Point, + button input.Button, + modifiers input.Modifiers, +) { if button == input.ButtonLeft { element.dragging = 0 }