hover&unhover events

This commit is contained in:
Michael Freno
2025-12-11 13:06:50 -05:00
parent 0bceade7d5
commit 56c8e744d5
7 changed files with 742 additions and 230 deletions

View File

@@ -152,12 +152,65 @@ function EventHandler:processMouseEvents(element, mx, my, isHovering, isActiveEl
end
end
end
-- Track hover state changes even when events can't be processed
-- Fire unhover event if we were hovering and now we're not
if self._hovered and not isHovering then
self._hovered = false
-- Fire unhover event if handler exists
if self.onEvent then
local modifiers = EventHandler._utils.getModifiers()
local unhoverEvent = EventHandler._InputEvent.new({
type = "unhover",
button = 0,
x = mx,
y = my,
modifiers = modifiers,
clickCount = 0,
})
self:_invokeCallback(element, unhoverEvent)
end
end
if EventHandler._Performance and EventHandler._Performance.enabled then
EventHandler._Performance:stopTimer("event_mouse")
end
return
end
-- Track hover state changes and fire hover/unhover events BEFORE button processing
-- This ensures hover fires before press when mouse first enters element
local wasHovered = self._hovered
local isHoveringAndActive = isHovering and isActiveElement
if isHoveringAndActive and not wasHovered then
-- Just started hovering - fire hover event
self._hovered = true
local modifiers = EventHandler._utils.getModifiers()
local hoverEvent = EventHandler._InputEvent.new({
type = "hover",
button = 0,
x = mx,
y = my,
modifiers = modifiers,
clickCount = 0,
})
self:_invokeCallback(element, hoverEvent)
elseif not isHoveringAndActive and wasHovered then
-- Just stopped hovering - fire unhover event
self._hovered = false
local modifiers = EventHandler._utils.getModifiers()
local unhoverEvent = EventHandler._InputEvent.new({
type = "unhover",
button = 0,
x = mx,
y = my,
modifiers = modifiers,
clickCount = 0,
})
self:_invokeCallback(element, unhoverEvent)
end
-- Process all three mouse buttons
local buttons = { 1, 2, 3 } -- left, right, middle

View File

@@ -1,5 +1,5 @@
---@class InputEvent
---@field type "click"|"press"|"release"|"rightclick"|"middleclick"|"drag"|"touchpress"|"touchmove"|"touchrelease"|"touchcancel"
---@field type "click"|"press"|"release"|"rightclick"|"middleclick"|"drag"|"hover"|"unhover"|"touchpress"|"touchmove"|"touchrelease"|"touchcancel"
---@field button number -- Mouse button: 1 (left), 2 (right), 3 (middle)
---@field x number -- Mouse/Touch X position
---@field y number -- Mouse/Touch Y position
@@ -15,7 +15,7 @@ local InputEvent = {}
InputEvent.__index = InputEvent
---@class InputEventProps
---@field type "click"|"press"|"release"|"rightclick"|"middleclick"|"drag"|"touchpress"|"touchmove"|"touchrelease"|"touchcancel"
---@field type "click"|"press"|"release"|"rightclick"|"middleclick"|"drag"|"hover"|"unhover"|"touchpress"|"touchmove"|"touchrelease"|"touchcancel"
---@field button number
---@field x number
---@field y number
@@ -42,12 +42,12 @@ function InputEvent.new(props)
self.modifiers = props.modifiers
self.clickCount = props.clickCount or 1
self.timestamp = props.timestamp or love.timer.getTime()
-- Touch-specific properties
self.touchId = props.touchId
self.pressure = props.pressure or 1.0
self.phase = props.phase
return self
end
@@ -68,7 +68,7 @@ function InputEvent.fromTouch(id, x, y, phase, pressure)
elseif phase == "cancelled" then
eventType = "touchcancel"
end
return InputEvent.new({
type = eventType,
button = 1, -- Treat touch as left button
@@ -76,7 +76,7 @@ function InputEvent.fromTouch(id, x, y, phase, pressure)
y = y,
dx = 0,
dy = 0,
modifiers = {shift = false, ctrl = false, alt = false, super = false},
modifiers = { shift = false, ctrl = false, alt = false, super = false },
clickCount = 1,
timestamp = love.timer.getTime(),
touchId = touchIdStr,