图库: 锁屏 PIN 改页内自绘 12 键数字键盘(不再弹系统 IME)
真机 goodix 抬手长尾会让阻塞式 MEOW_IME_NUM 打开即被「点背景=取消」 关掉,表现为「PIN 按钮点好几下才弹键盘」。锁屏改自绘 3×4 键盘 (1-9 / 退格·0·确认,键 137×96、间距 10px、底边留 28px 上滑热区), 完全离线、无 IME 会话,首次点按必响应。 - 4-8 位(MR_PIN_MIN_LEN/MAX_LEN),顶部星号显示已输入位数,不回显明文; 满 4 位后「确认」才可用;错误→提示+清空;通过→page_pop 回书库 - 长按退格清空;退格空缓冲为 no-op;8 位上限截断 - 颜色全部取 meow_theme_get();按键走 meow_btn_create_variant(TONAL/ OUTLINED/FILLED),沿用 SDK 按压高亮/禁用变淡 - 锁屏仍消费全部 SWIPE/TAP/LONG_PRESS(左缘绕过 PIN 的路径不变), 物理键返回 0 交 app.c on_key 仅日志 - 与设置页共用 logic/pin 的 mr_pin_verify/mr_pin_set,不复制校验逻辑 - 日志:lock: pad ready / pin wrong / pin ok(真机验收判据) test_settings_lock_host.c:锁屏用例从 IME 注入改为按键点击(12 键归属、 键高/间距/热区几何、空确认/不足 4 位、错 PIN 清空重输、8 位上限+退格、 空退格、长按清空、不打开系统 IME);设置页仍走真实 IME 注入路径。
This commit is contained in:
1 parent
2af7095d35
commit
606a04a44e
2 files changed
+303
-92
No files matched your search
@@ -8,8 +8,11 @@
|
||||
* 的 on_swipe),否则左缘返回会把 ACT_LOCK page_pop 掉、PIN 被绕过。
|
||||
* 另外覆盖:设置页回到书库(topbar 返回)、控件跨进出复用不重建、阅读方向经
|
||||
* mr_reader_set_direction 切换、lock_view_should_show() 随 PIN 状态变化、
|
||||
* 主题模式切换后整帧重绘不崩,以及**真实 MEOW_IME_NUM 键盘**驱动的两条端到端路径:
|
||||
* 锁屏错 PIN(留在锁屏)→ 对 PIN(page_pop 回书库)、设置页两遍输入开启 PIN。
|
||||
* 主题模式切换后整帧重绘不崩,以及两条端到端路径:
|
||||
* - **锁屏页内自绘 12 键数字键盘**(1-9 / 退格·0·确认):错 PIN 留在锁屏 → 对 PIN
|
||||
* page_pop 回书库;位数不足确认不可用、超长输入截断、退格/长按清空、错误后清空重输;
|
||||
* 键高/间距/屏底 28px 热区几何契约;
|
||||
* - 设置页两遍输入开启 PIN(仍走真实 MEOW_IME_NUM 键盘注入)。
|
||||
*
|
||||
* 编译:见 test/run_tests.sh —— 它把本测试、settings/lock/pin 源码与 SDK 源码
|
||||
* (-DMEOW_UI_HOST_TEST,附 test_host_stub.c 打桩 font/global)一起编;SDK 对象清单在脚本里。
|
||||
@@ -88,15 +91,44 @@ static void *pin_injector(void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void lock_try_pin(const char *digits)
|
||||
/* ============================================================ */
|
||||
/* 锁屏页内自绘 12 键数字键盘(宿主没有真实触摸):按 widget 矩形中心投递 TAP。
|
||||
* 键下标 = lock.c 创建序:0..8 = 1..9,9 = 退格,10 = 0,11 = 确认(LK_K*)。
|
||||
* ============================================================ */
|
||||
enum { LK_K1 = 0, LK_K9 = 8, LK_KBACK = 9, LK_K0 = 10, LK_KOK = 11 };
|
||||
|
||||
static int lock_key_center(meow_view *lock, int idx, int *cx, int *cy)
|
||||
{
|
||||
int sb = meow_ui_statusbar_height();
|
||||
int cy = sb + (meow_ui_height() - sb) / 2;
|
||||
pin_job job = { digits, 1 };
|
||||
pthread_t th;
|
||||
if (pthread_create(&th, NULL, pin_injector, &job) != 0) return;
|
||||
meow_view_dispatch_event(MEOW_EV_TAP, 240, cy + 40); /* 点「输入 PIN」按钮 */
|
||||
pthread_join(th, NULL);
|
||||
int r[4] = { 0 };
|
||||
if (!lock || idx < 0 || idx >= lock->nwidgets || !lock->widgets[idx]) return 0;
|
||||
meow_widget_rect(lock->widgets[idx], r);
|
||||
*cx = r[0] + r[2] / 2;
|
||||
*cy = r[1] + r[3] / 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void lock_tap_key(meow_view *lock, int idx)
|
||||
{
|
||||
int cx, cy;
|
||||
if (lock_key_center(lock, idx, &cx, &cy))
|
||||
meow_view_dispatch_event(MEOW_EV_TAP, cx, cy);
|
||||
}
|
||||
|
||||
static int lock_key_idx(char d)
|
||||
{
|
||||
return (d == '0') ? LK_K0 : (d - '1');
|
||||
}
|
||||
|
||||
static void lock_type(meow_view *lock, const char *digits)
|
||||
{
|
||||
for (const char *s = digits; *s; s++) lock_tap_key(lock, lock_key_idx(*s));
|
||||
}
|
||||
|
||||
static void lock_long_back(meow_view *lock)
|
||||
{
|
||||
int cx, cy;
|
||||
if (lock_key_center(lock, LK_KBACK, &cx, &cy))
|
||||
meow_view_dispatch_event(MEOW_EV_LONG_PRESS, cx, cy);
|
||||
}
|
||||
|
||||
static void settings_tap_pin_row(void){
|
||||
@@ -182,8 +214,31 @@ int main(void)
|
||||
|
||||
meow_view_page_push(ACT_LOCK);
|
||||
CHECK(meow_ui_activity_active() == ACT_LOCK, "lock active");
|
||||
CHECK(lock->nwidgets == 1, "lock built its button on enter (got %d)", lock->nwidgets);
|
||||
CHECK(meow_widget_owner(lock->widgets[0]) == ACT_LOCK, "lock button owned by ACT_LOCK");
|
||||
CHECK(lock->nwidgets == 12, "lock built 12-key pad on enter (got %d)", lock->nwidgets);
|
||||
int lock_owner_ok = 1;
|
||||
for (int i = 0; i < lock->nwidgets; i++)
|
||||
if (meow_widget_owner(lock->widgets[i]) != ACT_LOCK) lock_owner_ok = 0;
|
||||
CHECK(lock_owner_ok, "pad keys owned by ACT_LOCK (no cross-page leak)");
|
||||
|
||||
/* 几何契约:键 ≥64px 高、间距 ≥8px、不覆盖屏底 28px 上滑热区、全在屏内。 */
|
||||
int rk[12][4];
|
||||
for (int i = 0; i < 12; i++) meow_widget_rect(lock->widgets[i], rk[i]);
|
||||
int geo_ok = 1, gap_ok = 1, hot_ok = 1;
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (rk[i][2] < 64 || rk[i][3] < 64) geo_ok = 0;
|
||||
if (rk[i][0] < 0 || rk[i][0] + rk[i][2] > meow_ui_width()) geo_ok = 0;
|
||||
if (rk[i][1] + rk[i][3] > meow_ui_height() - 28) hot_ok = 0;
|
||||
}
|
||||
/* 列间距(行内 0/1/2)与行间距(行 0 与行 3:下标 0 与 9)。 */
|
||||
if (rk[1][0] - (rk[0][0] + rk[0][2]) < 8) gap_ok = 0;
|
||||
if (rk[2][0] - (rk[1][0] + rk[1][2]) < 8) gap_ok = 0;
|
||||
if (rk[9][1] - (rk[0][1] + rk[0][3]) < 8) gap_ok = 0;
|
||||
CHECK(geo_ok, "pad keys >=64px and within screen");
|
||||
CHECK(gap_ok, "pad gaps >=8px");
|
||||
CHECK(hot_ok, "pad leaves the 28px bottom swipe hot zone");
|
||||
printf(" pad geometry: key %dx%d, pad top=%d bottom=%d (screen %dx%d)\n",
|
||||
rk[0][2], rk[0][3], rk[0][1], rk[11][1] + rk[11][3],
|
||||
meow_ui_width(), meow_ui_height());
|
||||
|
||||
CHECK(meow_view_dispatch_event(MEOW_EV_SWIPE, MEOW_SWIPE_LEFT, 240) == 1,
|
||||
"lock consumes SWIPE (left-edge back cannot bypass PIN)");
|
||||
@@ -194,11 +249,53 @@ int main(void)
|
||||
CHECK(mr_pin_verify("1357") == 1, "stored PIN verifies");
|
||||
CHECK(mr_pin_verify("1358") == 0, "wrong PIN rejected");
|
||||
|
||||
/* ---- 锁屏真解锁路径:点按钮 → MEOW_IME_NUM 输入 → 校验 → pop(错误则留在锁屏) ---- */
|
||||
lock_try_pin("1358"); /* 错 PIN:留在锁屏 */
|
||||
/* 空输入 / 位数不足:确认不可用(不误判、不退出锁屏)。 */
|
||||
lock_tap_key(lock, LK_KOK);
|
||||
CHECK(meow_ui_activity_active() == ACT_LOCK, "empty confirm keeps lock");
|
||||
lock_type(lock, "135");
|
||||
lock_tap_key(lock, LK_KOK);
|
||||
CHECK(meow_ui_activity_active() == ACT_LOCK, "confirm disabled below 4 digits");
|
||||
|
||||
/* 第 4 位后确认可用:1-3-5-7 → 回书库。 */
|
||||
lock_tap_key(lock, lock_key_idx('7'));
|
||||
lock_tap_key(lock, LK_KOK);
|
||||
CHECK(meow_ui_activity_active() == ACT_LIBRARY, "4-digit correct PIN pops lock to library");
|
||||
CHECK(meow_ime_active() == 0, "in-page pad never opens the system IME");
|
||||
|
||||
/* 错 PIN:留在锁屏 + 清空;再输对 → 解锁(证明错误后缓冲已清空)。 */
|
||||
meow_view_page_push(ACT_LOCK);
|
||||
lock_type(lock, "1358");
|
||||
lock_tap_key(lock, LK_KOK);
|
||||
CHECK(meow_ui_activity_active() == ACT_LOCK, "wrong PIN keeps lock (retry allowed)");
|
||||
lock_try_pin("1357"); /* 正确:page_pop 回书库 */
|
||||
CHECK(meow_ui_activity_active() == ACT_LIBRARY, "correct PIN pops lock to library");
|
||||
lock_type(lock, "1357");
|
||||
lock_tap_key(lock, LK_KOK);
|
||||
CHECK(meow_ui_activity_active() == ACT_LIBRARY,
|
||||
"retry after wrong PIN unlocks (buffer cleared on error)");
|
||||
|
||||
/* 8 位上限:9 个键只收前 8 位;退格 4 次回到 "1357" → 解锁。 */
|
||||
meow_view_page_push(ACT_LOCK);
|
||||
lock_type(lock, "135713579");
|
||||
for (int i = 0; i < 4; i++) lock_tap_key(lock, LK_KBACK);
|
||||
lock_tap_key(lock, LK_KOK);
|
||||
CHECK(meow_ui_activity_active() == ACT_LIBRARY,
|
||||
"9th digit ignored (max 8) + backspace removes digits");
|
||||
|
||||
/* 退格空缓冲边界:多按不崩,随后正常输入。 */
|
||||
meow_view_page_push(ACT_LOCK);
|
||||
for (int i = 0; i < 3; i++) lock_tap_key(lock, LK_KBACK);
|
||||
lock_type(lock, "1357");
|
||||
lock_tap_key(lock, LK_KOK);
|
||||
CHECK(meow_ui_activity_active() == ACT_LIBRARY, "backspace on empty buffer is a no-op");
|
||||
|
||||
/* 长按退格清空:先输 3 位 → 长按清空 → 再输 4 位正确 PIN 才解锁。 */
|
||||
meow_view_page_push(ACT_LOCK);
|
||||
lock_type(lock, "135");
|
||||
lock_long_back(lock);
|
||||
lock_tap_key(lock, LK_KOK);
|
||||
CHECK(meow_ui_activity_active() == ACT_LOCK, "long-press backspace cleared input");
|
||||
lock_type(lock, "1357");
|
||||
lock_tap_key(lock, LK_KOK);
|
||||
CHECK(meow_ui_activity_active() == ACT_LIBRARY, "unlock after long-press clear");
|
||||
|
||||
/* ---- 设置页两遍输入开启 PIN(MEOW_IME_NUM) ---- */
|
||||
mr_pin_disable();
|
||||
|
||||
Reference in new issue
Block a user