You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Trying to finish keyboard
This commit is contained in:
@@ -20,6 +20,7 @@ Usage:
|
||||
|
||||
import lvgl as lv
|
||||
import mpos.ui.theme
|
||||
import time
|
||||
|
||||
|
||||
class MposKeyboard:
|
||||
@@ -60,6 +61,14 @@ class MposKeyboard:
|
||||
# Store textarea reference (we DON'T pass it to LVGL to avoid double-typing)
|
||||
self._textarea = None
|
||||
|
||||
# Track last mode switch time to prevent race conditions
|
||||
# When user rapidly clicks mode buttons, button indices can get confused
|
||||
# because index 29 is "abc" in numbers mode but "," in lowercase mode
|
||||
self._last_mode_switch_time = 0
|
||||
|
||||
# Re-entrancy guard to prevent recursive event processing during mode switches
|
||||
self._in_mode_switch = False
|
||||
|
||||
# Configure layouts
|
||||
self._setup_layouts()
|
||||
|
||||
@@ -148,11 +157,20 @@ class MposKeyboard:
|
||||
# This prevents LVGL's default handler from interfering
|
||||
event.stop_processing()
|
||||
|
||||
# Re-entrancy guard: Skip processing if we're currently switching modes
|
||||
# This prevents set_mode() from triggering recursive event processing
|
||||
if self._in_mode_switch:
|
||||
return
|
||||
|
||||
# Get the pressed button and its text
|
||||
button = self._keyboard.get_selected_button()
|
||||
current_mode = self._keyboard.get_mode()
|
||||
text = self._keyboard.get_button_text(button)
|
||||
|
||||
# Ignore if no valid button text (can happen during initialization)
|
||||
# DEBUG
|
||||
print(f"[KBD] btn={button}, mode={current_mode}, text='{text}'")
|
||||
|
||||
# Ignore if no valid button text (can happen during mode switching)
|
||||
if text is None:
|
||||
return
|
||||
|
||||
@@ -245,29 +263,29 @@ class MposKeyboard:
|
||||
mode: One of MODE_LOWERCASE, MODE_UPPERCASE, MODE_NUMBERS, MODE_SPECIALS
|
||||
(can also accept standard LVGL modes)
|
||||
"""
|
||||
# Determine which layout we're switching to
|
||||
# We need to set the map for BOTH the USER mode and the corresponding standard mode
|
||||
# to prevent crashes if LVGL internally switches between them
|
||||
# Map modes to their layouts
|
||||
mode_info = {
|
||||
self.MODE_LOWERCASE: (self._lowercase_map, self._lowercase_ctrl, [self.MODE_LOWERCASE, lv.keyboard.MODE.TEXT_LOWER]),
|
||||
self.MODE_UPPERCASE: (self._uppercase_map, self._uppercase_ctrl, [self.MODE_UPPERCASE, lv.keyboard.MODE.TEXT_UPPER]),
|
||||
self.MODE_NUMBERS: (self._numbers_map, self._numbers_ctrl, [self.MODE_NUMBERS, lv.keyboard.MODE.NUMBER]),
|
||||
self.MODE_SPECIALS: (self._specials_map, self._specials_ctrl, [self.MODE_SPECIALS, lv.keyboard.MODE.SPECIAL]),
|
||||
# Also support standard LVGL modes
|
||||
lv.keyboard.MODE.TEXT_LOWER: (self._lowercase_map, self._lowercase_ctrl, [self.MODE_LOWERCASE, lv.keyboard.MODE.TEXT_LOWER]),
|
||||
lv.keyboard.MODE.TEXT_UPPER: (self._uppercase_map, self._uppercase_ctrl, [self.MODE_UPPERCASE, lv.keyboard.MODE.TEXT_UPPER]),
|
||||
lv.keyboard.MODE.NUMBER: (self._numbers_map, self._numbers_ctrl, [self.MODE_NUMBERS, lv.keyboard.MODE.NUMBER]),
|
||||
lv.keyboard.MODE.SPECIAL: (self._specials_map, self._specials_ctrl, [self.MODE_SPECIALS, lv.keyboard.MODE.SPECIAL]),
|
||||
self.MODE_LOWERCASE: (self._lowercase_map, self._lowercase_ctrl),
|
||||
self.MODE_UPPERCASE: (self._uppercase_map, self._uppercase_ctrl),
|
||||
self.MODE_NUMBERS: (self._numbers_map, self._numbers_ctrl),
|
||||
self.MODE_SPECIALS: (self._specials_map, self._specials_ctrl),
|
||||
}
|
||||
|
||||
if mode in mode_info:
|
||||
key_map, ctrl_map, mode_list = mode_info[mode]
|
||||
# CRITICAL: Set the map for BOTH modes to prevent NULL pointer crashes
|
||||
# This ensures the map is set regardless of which mode LVGL uses internally
|
||||
for m in mode_list:
|
||||
self._keyboard.set_map(m, key_map, ctrl_map)
|
||||
# Set re-entrancy guard to block any events triggered during mode switch
|
||||
self._in_mode_switch = True
|
||||
|
||||
self._keyboard.set_mode(mode)
|
||||
try:
|
||||
# Set the map for the new mode BEFORE calling set_mode()
|
||||
# This prevents crashes from set_mode() being called with no map set
|
||||
if mode in mode_info:
|
||||
key_map, ctrl_map = mode_info[mode]
|
||||
self._keyboard.set_map(mode, key_map, ctrl_map)
|
||||
|
||||
# Now switch to the new mode
|
||||
self._keyboard.set_mode(mode)
|
||||
finally:
|
||||
# Always clear the guard, even if an exception occurs
|
||||
self._in_mode_switch = False
|
||||
|
||||
# ========================================================================
|
||||
# Python magic method for automatic method forwarding
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
"""
|
||||
Manual test for the "abc" button bug with DEBUG OUTPUT.
|
||||
|
||||
Run with: ./scripts/run_desktop.sh tests/manual_test_abc_button_debug.py
|
||||
|
||||
This will show debug output when you click the "abc" button.
|
||||
Watch the terminal to see what's happening!
|
||||
"""
|
||||
|
||||
import lvgl as lv
|
||||
from mpos.ui.keyboard import MposKeyboard
|
||||
|
||||
# Get active screen
|
||||
screen = lv.screen_active()
|
||||
screen.clean()
|
||||
|
||||
# Create title
|
||||
title = lv.label(screen)
|
||||
title.set_text("ABC Button Debug Test")
|
||||
title.align(lv.ALIGN.TOP_MID, 0, 5)
|
||||
|
||||
# Create instructions
|
||||
instructions = lv.label(screen)
|
||||
instructions.set_text(
|
||||
"Watch the TERMINAL output!\n"
|
||||
"\n"
|
||||
"1. Click '?123' to go to numbers mode\n"
|
||||
"2. Click 'abc' to go back to lowercase\n"
|
||||
"3. Check terminal for debug output\n"
|
||||
"4. Check if comma appears in textarea"
|
||||
)
|
||||
instructions.set_style_text_align(lv.TEXT_ALIGN.LEFT, 0)
|
||||
instructions.align(lv.ALIGN.TOP_LEFT, 10, 30)
|
||||
|
||||
# Create textarea
|
||||
textarea = lv.textarea(screen)
|
||||
textarea.set_size(280, 30)
|
||||
textarea.set_one_line(True)
|
||||
textarea.align(lv.ALIGN.TOP_MID, 0, 120)
|
||||
textarea.set_placeholder_text("Type here...")
|
||||
|
||||
# Create keyboard
|
||||
keyboard = MposKeyboard(screen)
|
||||
keyboard.set_textarea(textarea)
|
||||
keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
|
||||
|
||||
print("\n" + "="*70)
|
||||
print("ABC BUTTON DEBUG TEST")
|
||||
print("="*70)
|
||||
print("Instructions:")
|
||||
print("1. The keyboard starts in LOWERCASE mode")
|
||||
print("2. Click the '?123' button (bottom left) to switch to NUMBERS mode")
|
||||
print("3. Click the 'abc' button (bottom left) to switch back to LOWERCASE")
|
||||
print("4. Watch this terminal for [KEYBOARD DEBUG] messages")
|
||||
print("5. Check if a comma appears in the textarea")
|
||||
print("="*70)
|
||||
print("\nWaiting for button clicks...")
|
||||
print()
|
||||
@@ -0,0 +1,107 @@
|
||||
"""
|
||||
Automated test that simulates clicking the abc button and shows debug output.
|
||||
|
||||
This will show us exactly what's happening when the abc button is clicked.
|
||||
|
||||
Usage:
|
||||
Desktop: ./tests/unittest.sh tests/test_graphical_abc_button_debug.py
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import lvgl as lv
|
||||
from mpos.ui.keyboard import MposKeyboard
|
||||
from graphical_test_helper import wait_for_render
|
||||
|
||||
|
||||
class TestAbcButtonDebug(unittest.TestCase):
|
||||
"""Test that shows debug output when clicking abc button."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test fixtures."""
|
||||
self.screen = lv.obj()
|
||||
self.screen.set_size(320, 240)
|
||||
|
||||
# Create textarea
|
||||
self.textarea = lv.textarea(self.screen)
|
||||
self.textarea.set_size(280, 40)
|
||||
self.textarea.align(lv.ALIGN.TOP_MID, 0, 10)
|
||||
self.textarea.set_one_line(True)
|
||||
|
||||
# Load screen
|
||||
lv.screen_load(self.screen)
|
||||
wait_for_render(5)
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up."""
|
||||
lv.screen_load(lv.obj())
|
||||
wait_for_render(5)
|
||||
|
||||
def test_simulate_abc_button_click(self):
|
||||
"""
|
||||
Simulate clicking the abc button and show what happens.
|
||||
"""
|
||||
print("\n" + "="*70)
|
||||
print("SIMULATING ABC BUTTON CLICK - WATCH FOR DEBUG OUTPUT")
|
||||
print("="*70)
|
||||
|
||||
keyboard = MposKeyboard(self.screen)
|
||||
keyboard.set_textarea(self.textarea)
|
||||
keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
|
||||
wait_for_render(10)
|
||||
|
||||
# Start in lowercase, switch to numbers
|
||||
print("\n>>> Switching to NUMBERS mode...")
|
||||
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
|
||||
wait_for_render(10)
|
||||
|
||||
# Wait for debounce period to expire (150ms + margin)
|
||||
import time
|
||||
print(">>> Waiting 200ms for debounce period to expire...")
|
||||
time.sleep(0.2)
|
||||
|
||||
# Clear textarea
|
||||
self.textarea.set_text("")
|
||||
print(f">>> Textarea cleared: '{self.textarea.get_text()}'")
|
||||
|
||||
# Find the "abc" button
|
||||
abc_button_index = None
|
||||
for i in range(100):
|
||||
try:
|
||||
text = keyboard.get_button_text(i)
|
||||
if text == "abc":
|
||||
abc_button_index = i
|
||||
print(f">>> Found 'abc' button at index {abc_button_index}")
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
# Now simulate what happens when user TOUCHES the button
|
||||
# When user touches a button, LVGL's button matrix:
|
||||
# 1. Sets the button as selected
|
||||
# 2. Triggers VALUE_CHANGED event
|
||||
print(f"\n>>> Simulating user clicking button {abc_button_index}...")
|
||||
print(f">>> Before click: textarea = '{self.textarea.get_text()}'")
|
||||
print("\n--- DEBUG OUTPUT SHOULD APPEAR BELOW ---\n")
|
||||
|
||||
# Trigger the VALUE_CHANGED event which our handler catches
|
||||
# This simulates a real button press
|
||||
keyboard._keyboard.send_event(lv.EVENT.VALUE_CHANGED, None)
|
||||
wait_for_render(5)
|
||||
|
||||
print("\n--- END DEBUG OUTPUT ---\n")
|
||||
|
||||
textarea_after = self.textarea.get_text()
|
||||
print(f">>> After click: textarea = '{textarea_after}'")
|
||||
|
||||
if textarea_after != "":
|
||||
print(f"\n❌ BUG CONFIRMED!")
|
||||
print(f" Expected: '' (empty)")
|
||||
print(f" Got: '{textarea_after}'")
|
||||
else:
|
||||
print(f"\n✓ No text added (but check debug output above)")
|
||||
|
||||
print("="*70)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,162 @@
|
||||
"""
|
||||
Test for the abc button click bug - comma being added.
|
||||
|
||||
This test actually CLICKS the abc button to reproduce the comma bug.
|
||||
|
||||
Usage:
|
||||
Desktop: ./tests/unittest.sh tests/test_graphical_keyboard_abc_click_bug.py
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import lvgl as lv
|
||||
from mpos.ui.keyboard import MposKeyboard
|
||||
from graphical_test_helper import wait_for_render
|
||||
|
||||
|
||||
class TestAbcButtonClickBug(unittest.TestCase):
|
||||
"""Test that clicking abc button doesn't add comma."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test fixtures."""
|
||||
self.screen = lv.obj()
|
||||
self.screen.set_size(320, 240)
|
||||
|
||||
# Create textarea
|
||||
self.textarea = lv.textarea(self.screen)
|
||||
self.textarea.set_size(280, 40)
|
||||
self.textarea.align(lv.ALIGN.TOP_MID, 0, 10)
|
||||
self.textarea.set_one_line(True)
|
||||
|
||||
# Load screen
|
||||
lv.screen_load(self.screen)
|
||||
wait_for_render(5)
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up."""
|
||||
lv.screen_load(lv.obj())
|
||||
wait_for_render(5)
|
||||
|
||||
def test_clicking_abc_button_should_not_add_comma(self):
|
||||
"""
|
||||
Test that actually CLICKING the abc button doesn't add comma.
|
||||
|
||||
This is the REAL test - simulating actual user clicks.
|
||||
"""
|
||||
print("\n=== Testing ACTUAL CLICKING of abc button ===")
|
||||
|
||||
keyboard = MposKeyboard(self.screen)
|
||||
keyboard.set_textarea(self.textarea)
|
||||
keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
|
||||
wait_for_render(10)
|
||||
|
||||
# Start in lowercase, switch to numbers
|
||||
print("Step 1: Switch to numbers mode")
|
||||
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
|
||||
wait_for_render(10)
|
||||
|
||||
# Clear textarea
|
||||
self.textarea.set_text("")
|
||||
print(f" Textarea cleared: '{self.textarea.get_text()}'")
|
||||
|
||||
# Find the "abc" button
|
||||
abc_button_index = None
|
||||
for i in range(100):
|
||||
try:
|
||||
text = keyboard.get_button_text(i)
|
||||
if text == "abc":
|
||||
abc_button_index = i
|
||||
print(f" Found 'abc' button at index {i}")
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
self.assertIsNotNone(abc_button_index, "Should find 'abc' button in numbers mode")
|
||||
|
||||
# ACTUALLY CLICK THE BUTTON
|
||||
print(f"\nStep 2: ACTUALLY CLICK button index {abc_button_index}")
|
||||
print(f" Before click: textarea='{self.textarea.get_text()}'")
|
||||
|
||||
# Simulate button click by sending CLICKED event to the button matrix
|
||||
# Get the underlying button matrix object
|
||||
btnm = keyboard._keyboard
|
||||
|
||||
# Method 1: Try to programmatically click the button
|
||||
# This simulates what happens when user actually touches the button
|
||||
btnm.set_selected_button(abc_button_index)
|
||||
wait_for_render(2)
|
||||
|
||||
# Send the VALUE_CHANGED event
|
||||
btnm.send_event(lv.EVENT.VALUE_CHANGED, None)
|
||||
wait_for_render(5)
|
||||
|
||||
textarea_after = self.textarea.get_text()
|
||||
print(f" After click: textarea='{textarea_after}'")
|
||||
|
||||
# Check if comma was added
|
||||
if "," in textarea_after:
|
||||
print(f"\n ❌ BUG CONFIRMED: Comma was added!")
|
||||
print(f" Textarea contains: '{textarea_after}'")
|
||||
self.fail(f"BUG: Clicking 'abc' button added comma! Textarea: '{textarea_after}'")
|
||||
|
||||
# Also check if anything else was added
|
||||
if textarea_after != "":
|
||||
print(f"\n ❌ BUG CONFIRMED: Something was added!")
|
||||
print(f" Expected: ''")
|
||||
print(f" Got: '{textarea_after}'")
|
||||
self.fail(f"BUG: Clicking 'abc' button added text! Textarea: '{textarea_after}'")
|
||||
|
||||
print(f"\n ✓ SUCCESS: No text added, textarea is still empty")
|
||||
|
||||
def test_clicking_abc_multiple_times(self):
|
||||
"""
|
||||
Test clicking abc button multiple times in a row.
|
||||
"""
|
||||
print("\n=== Testing MULTIPLE clicks of abc button ===")
|
||||
|
||||
keyboard = MposKeyboard(self.screen)
|
||||
keyboard.set_textarea(self.textarea)
|
||||
keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
|
||||
wait_for_render(10)
|
||||
|
||||
for attempt in range(5):
|
||||
print(f"\n--- Attempt {attempt + 1} ---")
|
||||
|
||||
# Go to numbers mode
|
||||
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
|
||||
wait_for_render(10)
|
||||
|
||||
# Clear textarea
|
||||
self.textarea.set_text("")
|
||||
|
||||
# Find abc button
|
||||
abc_button_index = None
|
||||
for i in range(100):
|
||||
try:
|
||||
text = keyboard.get_button_text(i)
|
||||
if text == "abc":
|
||||
abc_button_index = i
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
# Click it
|
||||
print(f"Clicking 'abc' at index {abc_button_index}")
|
||||
keyboard._keyboard.set_selected_button(abc_button_index)
|
||||
wait_for_render(2)
|
||||
keyboard._keyboard.send_event(lv.EVENT.VALUE_CHANGED, None)
|
||||
wait_for_render(5)
|
||||
|
||||
textarea_text = self.textarea.get_text()
|
||||
print(f" Result: textarea='{textarea_text}'")
|
||||
|
||||
if textarea_text != "":
|
||||
print(f" ❌ FAIL on attempt {attempt + 1}: Got '{textarea_text}'")
|
||||
self.fail(f"Attempt {attempt + 1}: Clicking 'abc' added '{textarea_text}'")
|
||||
else:
|
||||
print(f" ✓ OK")
|
||||
|
||||
print("\n✓ SUCCESS: All 5 attempts worked correctly")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,167 @@
|
||||
"""
|
||||
Test for rapid mode switching bug (clicking ?123/abc rapidly).
|
||||
|
||||
This test reproduces:
|
||||
1. Comma being added when clicking "abc" button
|
||||
2. Intermittent crashes when rapidly clicking mode switch buttons
|
||||
|
||||
Usage:
|
||||
Desktop: ./tests/unittest.sh tests/test_graphical_keyboard_rapid_mode_switch.py
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import lvgl as lv
|
||||
from mpos.ui.keyboard import MposKeyboard
|
||||
from graphical_test_helper import wait_for_render
|
||||
|
||||
|
||||
class TestRapidModeSwitching(unittest.TestCase):
|
||||
"""Test rapid mode switching between lowercase and numbers."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up test fixtures."""
|
||||
self.screen = lv.obj()
|
||||
self.screen.set_size(320, 240)
|
||||
|
||||
# Create textarea
|
||||
self.textarea = lv.textarea(self.screen)
|
||||
self.textarea.set_size(280, 40)
|
||||
self.textarea.align(lv.ALIGN.TOP_MID, 0, 10)
|
||||
self.textarea.set_one_line(True)
|
||||
|
||||
# Load screen
|
||||
lv.screen_load(self.screen)
|
||||
wait_for_render(5)
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up."""
|
||||
lv.screen_load(lv.obj())
|
||||
wait_for_render(5)
|
||||
|
||||
def test_rapid_clicking_abc_button(self):
|
||||
"""
|
||||
Rapidly click the "abc" button to reproduce the comma bug and crash.
|
||||
|
||||
Expected: Clicking "abc" should NOT add comma to textarea
|
||||
Bug: Comma is being added, suggesting button index confusion
|
||||
"""
|
||||
print("\n=== Testing rapid clicking of abc button ===")
|
||||
|
||||
keyboard = MposKeyboard(self.screen)
|
||||
keyboard.set_textarea(self.textarea)
|
||||
keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
|
||||
wait_for_render(10)
|
||||
|
||||
# Start in lowercase, switch to numbers
|
||||
print("Step 1: Switch to numbers mode")
|
||||
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
|
||||
wait_for_render(10) # Give time to settle
|
||||
|
||||
# Clear textarea
|
||||
self.textarea.set_text("")
|
||||
|
||||
# Now find the "abc" button
|
||||
abc_button_index = None
|
||||
for i in range(100):
|
||||
try:
|
||||
text = keyboard.get_button_text(i)
|
||||
if text == "abc":
|
||||
abc_button_index = i
|
||||
print(f" Found 'abc' button at index {i}")
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
self.assertIsNotNone(abc_button_index, "Should find 'abc' button in numbers mode")
|
||||
|
||||
# Simulate rapid clicking by alternating modes
|
||||
print("\nStep 2: Rapidly switch modes by simulating abc/?123 clicks")
|
||||
for i in range(10):
|
||||
# Get current mode
|
||||
current_mode = keyboard._keyboard.get_mode()
|
||||
|
||||
# Clear text before click
|
||||
textarea_before = self.textarea.get_text()
|
||||
print(f" Click {i+1}: mode={current_mode}, textarea='{textarea_before}'")
|
||||
|
||||
if current_mode == MposKeyboard.MODE_NUMBERS or current_mode == lv.keyboard.MODE.NUMBER:
|
||||
# Click "abc" to go to lowercase
|
||||
keyboard.set_mode(MposKeyboard.MODE_LOWERCASE)
|
||||
else:
|
||||
# Click "?123" to go to numbers
|
||||
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
|
||||
|
||||
wait_for_render(2)
|
||||
|
||||
# Check if text changed (BUG: should not change!)
|
||||
textarea_after = self.textarea.get_text()
|
||||
if textarea_after != textarea_before:
|
||||
print(f" ERROR: Text changed from '{textarea_before}' to '{textarea_after}'")
|
||||
self.fail(f"BUG: Clicking mode switch button added '{textarea_after}' to textarea")
|
||||
|
||||
# Verify textarea is still empty
|
||||
final_text = self.textarea.get_text()
|
||||
print(f"\nFinal textarea text: '{final_text}'")
|
||||
self.assertEqual(final_text, "",
|
||||
f"Textarea should be empty after mode switches, but contains: '{final_text}'")
|
||||
|
||||
print("SUCCESS: No spurious characters added during rapid mode switching")
|
||||
|
||||
def test_button_indices_after_mode_switch(self):
|
||||
"""
|
||||
Test that button indices remain consistent after mode switches.
|
||||
|
||||
This helps identify if the comma bug is due to button index confusion.
|
||||
"""
|
||||
print("\n=== Testing button indices after mode switch ===")
|
||||
|
||||
keyboard = MposKeyboard(self.screen)
|
||||
keyboard.set_textarea(self.textarea)
|
||||
keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
|
||||
wait_for_render(10)
|
||||
|
||||
# Map button indices in lowercase mode
|
||||
print("\nButton indices in LOWERCASE mode:")
|
||||
keyboard.set_mode(MposKeyboard.MODE_LOWERCASE)
|
||||
wait_for_render(10)
|
||||
|
||||
lowercase_buttons = {}
|
||||
for i in range(40):
|
||||
try:
|
||||
text = keyboard.get_button_text(i)
|
||||
if text in ["?123", ",", "abc", lv.SYMBOL.UP]:
|
||||
lowercase_buttons[text] = i
|
||||
print(f" '{text}' at index {i}")
|
||||
except:
|
||||
pass
|
||||
|
||||
# Map button indices in numbers mode
|
||||
print("\nButton indices in NUMBERS mode:")
|
||||
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
|
||||
wait_for_render(10)
|
||||
|
||||
numbers_buttons = {}
|
||||
for i in range(40):
|
||||
try:
|
||||
text = keyboard.get_button_text(i)
|
||||
if text in ["?123", ",", "abc", "=\\<"]:
|
||||
numbers_buttons[text] = i
|
||||
print(f" '{text}' at index {i}")
|
||||
except:
|
||||
pass
|
||||
|
||||
# Check if comma and abc are at same index
|
||||
if "," in lowercase_buttons and "abc" in numbers_buttons:
|
||||
comma_idx = lowercase_buttons[","]
|
||||
abc_idx = numbers_buttons["abc"]
|
||||
print(f"\nComparison:")
|
||||
print(f" Comma in lowercase: index {comma_idx}")
|
||||
print(f" 'abc' in numbers: index {abc_idx}")
|
||||
|
||||
if comma_idx == abc_idx:
|
||||
print(" WARNING: Comma and 'abc' share the same index!")
|
||||
print(" This could explain why comma appears when clicking 'abc'")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user