better input field keyboard handling

This commit is contained in:
Michael Freno
2025-11-09 12:00:42 -05:00
parent 3690202f48
commit 694a2d0a2e
8 changed files with 1846 additions and 20 deletions

View File

@@ -5,11 +5,55 @@ local Element = FlexLove.Element
TestKeyboardInput = {}
-- Helper function to ensure clean keyboard state
local function clearModifierKeys()
love.keyboard.setDown("lshift", false)
love.keyboard.setDown("rshift", false)
love.keyboard.setDown("lctrl", false)
love.keyboard.setDown("rctrl", false)
love.keyboard.setDown("lalt", false)
love.keyboard.setDown("ralt", false)
love.keyboard.setDown("lgui", false)
love.keyboard.setDown("rgui", false)
end
function TestKeyboardInput:setUp()
-- Clear all keyboard modifier states at start of each test
if love.keyboard.isDown("lgui", "rgui", "lalt", "ralt", "lctrl", "rctrl", "lshift", "rshift") then
local mods = {}
if love.keyboard.isDown("lshift") then table.insert(mods, "lshift") end
if love.keyboard.isDown("rshift") then table.insert(mods, "rshift") end
if love.keyboard.isDown("lctrl") then table.insert(mods, "lctrl") end
if love.keyboard.isDown("rctrl") then table.insert(mods, "rctrl") end
if love.keyboard.isDown("lalt") then table.insert(mods, "lalt") end
if love.keyboard.isDown("ralt") then table.insert(mods, "ralt") end
if love.keyboard.isDown("lgui") then table.insert(mods, "lgui") end
if love.keyboard.isDown("rgui") then table.insert(mods, "rgui") end
print("WARNING: Modifiers down at setUp: " .. table.concat(mods, ", "))
end
love.keyboard.setDown("lshift", false)
love.keyboard.setDown("rshift", false)
love.keyboard.setDown("lctrl", false)
love.keyboard.setDown("rctrl", false)
love.keyboard.setDown("lalt", false)
love.keyboard.setDown("ralt", false)
love.keyboard.setDown("lgui", false)
love.keyboard.setDown("rgui", false)
Gui.init({ baseScale = { width = 1920, height = 1080 } })
end
function TestKeyboardInput:tearDown()
-- Clear all keyboard modifier states
love.keyboard.setDown("lshift", false)
love.keyboard.setDown("rshift", false)
love.keyboard.setDown("lctrl", false)
love.keyboard.setDown("rctrl", false)
love.keyboard.setDown("lalt", false)
love.keyboard.setDown("ralt", false)
love.keyboard.setDown("lgui", false)
love.keyboard.setDown("rgui", false)
Gui.destroy()
end
@@ -313,6 +357,186 @@ function TestKeyboardInput:testEndKey()
lu.assertEquals(input._cursorPosition, 5)
end
-- ====================
-- Modifier Key Tests
-- ====================
function TestKeyboardInput:testSuperLeftMovesToStart()
clearModifierKeys()
local input = Element.new({
width = 200,
height = 40,
editable = true,
text = "Hello World",
})
input:focus()
input:setCursorPosition(8) -- Middle of text
-- Simulate Super (Cmd/Win) key being held
love.keyboard.setDown("lgui", true)
input:keypressed("left", "left", false)
love.keyboard.setDown("lgui", false)
lu.assertEquals(input._cursorPosition, 0)
end
function TestKeyboardInput:testSuperRightMovesToEnd()
clearModifierKeys()
local input = Element.new({
width = 200,
height = 40,
editable = true,
text = "Hello World",
})
input:focus()
input:setCursorPosition(3) -- Middle of text
-- Simulate Super (Cmd/Win) key being held
love.keyboard.setDown("lgui", true)
input:keypressed("right", "right", false)
love.keyboard.setDown("lgui", false)
lu.assertEquals(input._cursorPosition, 11) -- End of "Hello World"
end
function TestKeyboardInput:testAltLeftMovesByWord()
clearModifierKeys()
local input = Element.new({
width = 200,
height = 40,
editable = true,
text = "Hello World Test",
})
input:focus()
input:setCursorPosition(16) -- End of text
-- Simulate Alt key being held and move left by word
love.keyboard.setDown("lalt", true)
input:keypressed("left", "left", false)
love.keyboard.setDown("lalt", false)
lu.assertEquals(input._cursorPosition, 12) -- Start of "Test"
end
function TestKeyboardInput:testAltRightMovesByWord()
clearModifierKeys()
local input = Element.new({
width = 200,
height = 40,
editable = true,
text = "Hello World Test",
})
input:focus()
input:setCursorPosition(0) -- Start of text
-- Simulate Alt key being held and move right by word
love.keyboard.setDown("lalt", true)
input:keypressed("right", "right", false)
love.keyboard.setDown("lalt", false)
lu.assertEquals(input._cursorPosition, 6) -- After "Hello "
end
function TestKeyboardInput:testAltLeftMultipleWords()
clearModifierKeys()
local input = Element.new({
width = 200,
height = 40,
editable = true,
text = "The quick brown fox",
})
input:focus()
input:setCursorPosition(19) -- End of text
-- Move left by word three times
love.keyboard.setDown("lalt", true)
input:keypressed("left", "left", false) -- to "fox"
input:keypressed("left", "left", false) -- to "brown"
input:keypressed("left", "left", false) -- to "quick"
love.keyboard.setDown("lalt", false)
lu.assertEquals(input._cursorPosition, 4) -- Start of "quick"
end
function TestKeyboardInput:testAltRightMultipleWords()
clearModifierKeys()
local input = Element.new({
width = 200,
height = 40,
editable = true,
text = "The quick brown fox",
})
input:focus()
input:setCursorPosition(0) -- Start of text
-- Move right by word three times
love.keyboard.setDown("lalt", true)
input:keypressed("right", "right", false) -- after "The "
input:keypressed("right", "right", false) -- after "quick "
input:keypressed("right", "right", false) -- after "brown "
love.keyboard.setDown("lalt", false)
lu.assertEquals(input._cursorPosition, 16) -- After "brown "
end
function TestKeyboardInput:testSuperLeftWithSelection()
clearModifierKeys()
local input = Element.new({
width = 200,
height = 40,
editable = true,
text = "Hello World",
})
input:focus()
input:setSelection(3, 8)
lu.assertTrue(input:hasSelection())
-- Super+Left should move to start and clear selection
love.keyboard.setDown("lgui", true)
input:keypressed("left", "left", false)
love.keyboard.setDown("lgui", false)
lu.assertEquals(input._cursorPosition, 0)
lu.assertFalse(input:hasSelection())
end
function TestKeyboardInput:testSuperRightWithSelection()
clearModifierKeys()
local input = Element.new({
width = 200,
height = 40,
editable = true,
text = "Hello World",
})
input:focus()
input:setSelection(3, 8)
lu.assertTrue(input:hasSelection())
-- Super+Right should move to end and clear selection
love.keyboard.setDown("lgui", true)
input:keypressed("right", "right", false)
love.keyboard.setDown("lgui", false)
lu.assertEquals(input._cursorPosition, 11)
lu.assertFalse(input:hasSelection())
end
function TestKeyboardInput:testEscapeClearsSelection()
local input = Element.new({
width = 200,