You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Fix tests/test_graphical_keyboard_q_button_bug.py
This commit is contained in:
@@ -383,6 +383,104 @@ def find_button_with_text(obj, search_text):
|
||||
return None
|
||||
|
||||
|
||||
def get_keyboard_button_coords(keyboard, button_text):
|
||||
"""
|
||||
Get the coordinates of a specific button on an LVGL keyboard/buttonmatrix.
|
||||
|
||||
This function calculates the exact center position of a keyboard button
|
||||
by finding its index and computing its position based on the keyboard's
|
||||
layout, control widths, and actual screen coordinates.
|
||||
|
||||
Args:
|
||||
keyboard: LVGL keyboard widget (or MposKeyboard wrapper)
|
||||
button_text: Text of the button to find (e.g., "q", "a", "1")
|
||||
|
||||
Returns:
|
||||
dict with 'center_x' and 'center_y', or None if button not found
|
||||
|
||||
Example:
|
||||
from mpos.ui.keyboard import MposKeyboard
|
||||
keyboard = MposKeyboard(screen)
|
||||
coords = get_keyboard_button_coords(keyboard, "q")
|
||||
if coords:
|
||||
simulate_click(coords['center_x'], coords['center_y'])
|
||||
"""
|
||||
# Get the underlying LVGL keyboard if this is a wrapper
|
||||
if hasattr(keyboard, '_keyboard'):
|
||||
lvgl_keyboard = keyboard._keyboard
|
||||
else:
|
||||
lvgl_keyboard = keyboard
|
||||
|
||||
# Find the button index
|
||||
button_idx = None
|
||||
for i in range(100): # Check up to 100 buttons
|
||||
try:
|
||||
text = lvgl_keyboard.get_button_text(i)
|
||||
if text == button_text:
|
||||
button_idx = i
|
||||
break
|
||||
except:
|
||||
break # No more buttons
|
||||
|
||||
if button_idx is None:
|
||||
return None
|
||||
|
||||
# Get keyboard widget coordinates
|
||||
area = lv.area_t()
|
||||
lvgl_keyboard.get_coords(area)
|
||||
kb_x = area.x1
|
||||
kb_y = area.y1
|
||||
kb_width = area.x2 - area.x1
|
||||
kb_height = area.y2 - area.y1
|
||||
|
||||
# Parse the keyboard layout to find button position
|
||||
# Note: LVGL get_button_text() skips '\n' markers, so they're not in the indices
|
||||
# Standard keyboard layout (from MposKeyboard):
|
||||
# Row 0: 10 buttons (q w e r t y u i o p)
|
||||
# Row 1: 9 buttons (a s d f g h j k l)
|
||||
# Row 2: 9 buttons (shift z x c v b n m backspace)
|
||||
# Row 3: 5 buttons (?123, comma, space, dot, enter)
|
||||
|
||||
# Define row lengths for standard keyboard
|
||||
row_lengths = [10, 9, 9, 5]
|
||||
|
||||
# Find which row our button is in
|
||||
row = 0
|
||||
buttons_before = 0
|
||||
for row_len in row_lengths:
|
||||
if button_idx < buttons_before + row_len:
|
||||
# Button is in this row
|
||||
col = button_idx - buttons_before
|
||||
buttons_this_row = row_len
|
||||
break
|
||||
buttons_before += row_len
|
||||
row += 1
|
||||
else:
|
||||
# Button not found in standard layout, use row 0
|
||||
row = 0
|
||||
col = button_idx
|
||||
buttons_this_row = 10
|
||||
|
||||
# Calculate position
|
||||
# Approximate: divide keyboard into equal rows and columns
|
||||
# (This is simplified - actual LVGL uses control widths, but this is good enough)
|
||||
num_rows = 4 # Typical keyboard has 4 rows
|
||||
button_height = kb_height / num_rows
|
||||
button_width = kb_width / max(buttons_this_row, 1)
|
||||
|
||||
# Calculate center position
|
||||
center_x = int(kb_x + (col * button_width) + (button_width / 2))
|
||||
center_y = int(kb_y + (row * button_height) + (button_height / 2))
|
||||
|
||||
return {
|
||||
'center_x': center_x,
|
||||
'center_y': center_y,
|
||||
'button_idx': button_idx,
|
||||
'row': row,
|
||||
'col': col
|
||||
}
|
||||
|
||||
|
||||
def _touch_read_cb(indev_drv, data):
|
||||
"""
|
||||
Internal callback for simulated touch input device.
|
||||
|
||||
@@ -20,6 +20,7 @@ from mpos.ui.testing import (
|
||||
wait_for_render,
|
||||
find_button_with_text,
|
||||
get_widget_coords,
|
||||
get_keyboard_button_coords,
|
||||
simulate_click,
|
||||
print_screen_labels
|
||||
)
|
||||
@@ -79,43 +80,16 @@ class TestKeyboardQButton(unittest.TestCase):
|
||||
# --- Test 'q' button ---
|
||||
print("\n--- Testing 'q' button ---")
|
||||
|
||||
# Find button index for 'q' in the keyboard
|
||||
q_button_id = None
|
||||
for i in range(100): # Check first 100 button indices
|
||||
try:
|
||||
text = keyboard.get_button_text(i)
|
||||
if text == "q":
|
||||
q_button_id = i
|
||||
print(f"Found 'q' button at index {i}")
|
||||
break
|
||||
except:
|
||||
break # No more buttons
|
||||
# Get exact button coordinates using helper function
|
||||
q_coords = get_keyboard_button_coords(keyboard, "q")
|
||||
self.assertIsNotNone(q_coords, "Should find 'q' button on keyboard")
|
||||
|
||||
self.assertIsNotNone(q_button_id, "Should find 'q' button on keyboard")
|
||||
|
||||
# Get the keyboard widget coordinates to calculate button position
|
||||
keyboard_area = lv.area_t()
|
||||
keyboard.get_coords(keyboard_area)
|
||||
print(f"Keyboard area: x1={keyboard_area.x1}, y1={keyboard_area.y1}, x2={keyboard_area.x2}, y2={keyboard_area.y2}")
|
||||
|
||||
# LVGL keyboards organize buttons in a grid
|
||||
# From the map: "q" is at index 0, in top row (10 buttons per row)
|
||||
# Let's estimate position based on keyboard layout
|
||||
# Top row starts at y1 + some padding, each button is ~width/10
|
||||
keyboard_width = keyboard_area.x2 - keyboard_area.x1
|
||||
keyboard_height = keyboard_area.y2 - keyboard_area.y1
|
||||
button_width = keyboard_width // 10 # ~10 buttons per row
|
||||
button_height = keyboard_height // 4 # ~4 rows
|
||||
|
||||
# 'q' is first button (index 0), top row
|
||||
q_x = keyboard_area.x1 + button_width // 2
|
||||
q_y = keyboard_area.y1 + button_height // 2
|
||||
|
||||
print(f"Estimated 'q' button position: ({q_x}, {q_y})")
|
||||
print(f"Found 'q' button at index {q_coords['button_idx']}, row {q_coords['row']}, col {q_coords['col']}")
|
||||
print(f"Exact 'q' button position: ({q_coords['center_x']}, {q_coords['center_y']})")
|
||||
|
||||
# Click the 'q' button
|
||||
print(f"Clicking 'q' button at ({q_x}, {q_y})")
|
||||
simulate_click(q_x, q_y)
|
||||
print(f"Clicking 'q' button at ({q_coords['center_x']}, {q_coords['center_y']})")
|
||||
simulate_click(q_coords['center_x'], q_coords['center_y'])
|
||||
wait_for_render(10)
|
||||
|
||||
# Check textarea content
|
||||
@@ -134,29 +108,16 @@ class TestKeyboardQButton(unittest.TestCase):
|
||||
wait_for_render(5)
|
||||
print("Cleared textarea")
|
||||
|
||||
# Find button index for 'a'
|
||||
a_button_id = None
|
||||
for i in range(100):
|
||||
try:
|
||||
text = keyboard.get_button_text(i)
|
||||
if text == "a":
|
||||
a_button_id = i
|
||||
print(f"Found 'a' button at index {i}")
|
||||
break
|
||||
except:
|
||||
break
|
||||
# Get exact button coordinates using helper function
|
||||
a_coords = get_keyboard_button_coords(keyboard, "a")
|
||||
self.assertIsNotNone(a_coords, "Should find 'a' button on keyboard")
|
||||
|
||||
self.assertIsNotNone(a_button_id, "Should find 'a' button on keyboard")
|
||||
|
||||
# 'a' is at index 11 (second row, first position)
|
||||
a_x = keyboard_area.x1 + button_width // 2
|
||||
a_y = keyboard_area.y1 + button_height + button_height // 2
|
||||
|
||||
print(f"Estimated 'a' button position: ({a_x}, {a_y})")
|
||||
print(f"Found 'a' button at index {a_coords['button_idx']}, row {a_coords['row']}, col {a_coords['col']}")
|
||||
print(f"Exact 'a' button position: ({a_coords['center_x']}, {a_coords['center_y']})")
|
||||
|
||||
# Click the 'a' button
|
||||
print(f"Clicking 'a' button at ({a_x}, {a_y})")
|
||||
simulate_click(a_x, a_y)
|
||||
print(f"Clicking 'a' button at ({a_coords['center_x']}, {a_coords['center_y']})")
|
||||
simulate_click(a_coords['center_x'], a_coords['center_y'])
|
||||
wait_for_render(10)
|
||||
|
||||
# Check textarea content
|
||||
|
||||
Reference in New Issue
Block a user