Files
MeowOS-SDK/tuku/app.c
T
AskaEth 87f4ad0a82 图库: 锁屏长按退格在真机可达(仅在锁屏页启用长按)
M29 评审 P2-1:SDK 长按是 opt-in,全仓没有运行时调用
meow_ui_set_long_press_cb,meow_input_long_press_poll 恒返回 0,真机上
MEOW_EV_LONG_PRESS 永不产生——「长按退格清空」只表现为删一位。

- app.c 注册 no-op 长按回调,但只在 ACT_LOCK 为顶层页时启用(进主循环前对齐
  一次 + on_tick 每拍对齐),解锁 pop 后置 NULL。全程开启会让长按触发后的
  抬手不再产生 TAP/SWIPE,吞掉书库/阅读器里「按住 >=500ms」的点击。
- test_settings_lock_host:长按用例改走真实 SDK 路径——未注册 poll==0(P2
  根因)、注册后按住 700ms 产出 LONG_PRESS 且坐标=退格键心、被锁屏 view 消费、
  抬手不补发 TAP、解锁后关掉再 poll==0。
- lock.c 头注释补上该 opt-in 依赖,避免以后只看锁屏页时误判可达。
2026-11-06 11:46:31 +08:00

169 lines
5.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* app.c — 图库装配层:main + 建页 + meow_ui_run 回调路由 + 主题监听。
*
* 契约(docs/APP_DEV_GUIDE.md §2-§3):
* - main 只做 meow_ui_init → 建 view → meow_ui_run → 清理;退出走 meow_ui_request_exit;
* - 页面切换统一走 meow_view_page_push/pop(activity 栈 + on_enter/on_leave 唯一入口);
* - 物理键不映射返回/确认(on_key 仅日志);屏底上滑由 SDK 系统手势接管,App 不拦截;
* - 左缘返回:reader/settings=pop;lock 页自行消费;书库逐级上移,
* **到 TF 卡根=退出 App**(浏览根锁定,不再上溯系统目录;顶栏也没有越根的「上级」)。
*
* 主题同步:注册 meow_theme_add_listener;明暗/风格族切换时更新页面底色并整帧 invalidate,
* 各页 on_draw / SDK 控件下一帧即用新语义色重绘(不缓存颜色)。
*/
#include "tuku_internal.h"
#include "ui/reader/reader.h"
#include "meow_ui_nav.h"
#include <signal.h>
static void on_sigterm(int s)
{
(void)s;
meow_ui_request_exit();
}
/* 向 launcher 上报当前页栈深/顶层,供系统导航栈跟随。各页 on_enter 调用。 */
void mr_nav_report(void)
{
int depth = meow_ui_activity_depth();
if (depth <= 0) depth = 1;
int id = meow_ui_activity_active();
const char *top = (id == ACT_READER) ? "reader"
: (id == ACT_SETTINGS) ? "settings"
: (id == ACT_LOCK) ? "lock"
: "library";
meow_ui_nav_report((uint32_t)depth, top);
}
/* 主题切换:页面底色 + 整帧重绘(控件与 on_draw 全部从 meow_theme_get() 取色)。 */
static void app_theme_changed(meow_theme_mode m)
{
(void)m;
meow_ui_set_page_bg(meow_theme_get()->bg);
meow_ui_invalidate(0, 0, meow_ui_width(), meow_ui_height());
}
static int app_active(void)
{
return meow_ui_activity_active();
}
static void app_on_key(int keycode, int is_down)
{
(void)keycode; (void)is_down; /* 物理键是系统语义,不做返回/确认映射 */
meow_log(MEOW_LOG_DEBUG, "key");
}
static void app_on_tap(int x, int y)
{
switch (app_active()) {
case ACT_LIBRARY: library_on_tap(x, y); break;
case ACT_READER: reader_on_tap(x, y); break;
default: break;
}
}
static void app_on_swipe(int dir, int dx, int dy)
{
(void)dy;
if (dir == MEOW_SWIPE_LEFT) {
if (app_active() == ACT_LIBRARY) {
if (!library_go_up()) {
meow_log(MEOW_LOG_INFO, "exit:swipe");
meow_ui_request_exit();
}
} else {
meow_view_page_pop();
}
return;
}
/* SDK 的 on_swipe 把位移量放在第二参(第三参为 0):UP/DOWN 时 dx=纵向位移。 */
if (app_active() == ACT_LIBRARY) library_on_swipe(dir, dx);
}
/* 通用长按(SDK §6.3)是 opt-in:未注册回调时 meow_input_long_press_poll 直接返回 0,
* MEOW_EV_LONG_PRESS 永远不会产生 —— 锁屏的「长按退格清空」在真机上就退化成单删一位。
* 这里注册一个 no-op 回调把长按打开;事件仍然先经 meow_view_dispatch_event 路由,锁屏页
* 自己消费 LONG_PRESS(其它页命中不到就走 no-op)。
*
* 只在锁屏为顶层页时启用:长按一旦触发,其抬手不再产生 TAP/SWIPE(SDK 抑制点击),
* 全程开启会让书库/阅读器里「按住稍久」的点击被吞掉。锁屏页解锁 pop 后由 app_on_tick
* 下一拍关掉,避免把长按语义泄漏到其它页。 */
static int g_long_press_on;
static void app_on_long_press(int x, int y)
{
(void)x; (void)y; /* 锁屏已在 view 分发里消费;其余页没有长按语义 */
}
static void app_sync_long_press(void)
{
int on = (app_active() == ACT_LOCK);
if (on == g_long_press_on) return;
meow_ui_set_long_press_cb(on ? app_on_long_press : NULL);
g_long_press_on = on;
}
static void app_on_tick(void)
{
app_sync_long_press();
library_on_tick();
}
static void app_on_swipe_progress(int x_start, int dx)
{
meow_ui_swipe_hint(x_start + dx);
}
/* 跟手拖动路由(M6):ACT_READER 需要原始 down/move 算位移;其余页保持原语义。
* 屏底热区/左缘的避让由 reader 侧按同一口径判断(reader_on_touch_down)。 */
static void app_on_touch_down(int x, int y)
{
if (app_active() == ACT_LIBRARY) library_on_touch_down(x, y);
else if (app_active() == ACT_READER) reader_on_touch_down(x, y);
}
static void app_on_touch_move(int x, int y)
{
if (app_active() == ACT_LIBRARY) library_on_touch_move(x, y);
else if (app_active() == ACT_READER) reader_on_touch_move(x, y);
}
int main(void)
{
meow_log(MEOW_LOG_INFO, "start");
meow_ui_opts o = { 480, 720 };
if (meow_ui_init(&o) != 0) {
meow_log(MEOW_LOG_ERROR, "init failed");
return 1;
}
meow_theme_add_listener(app_theme_changed);
meow_ui_set_page_bg(meow_theme_get()->bg);
meow_ui_nav_init();
signal(SIGTERM, on_sigterm);
/* 先建全部页面(on_create 建各自控件/扫描书库),再按启动锁状态进根页。 */
meow_view *library = library_view_create();
meow_view *reader = reader_view_create();
meow_view *settings = settings_view_create();
meow_view *lock = lock_view_create();
meow_view_page_push(lock_view_should_show() ? ACT_LOCK : ACT_LIBRARY);
app_sync_long_press(); /* 进主循环前先对齐一次:启动即锁屏时首帧长按就可用 */
meow_ui_events ev = {
app_on_key, app_on_tap, app_on_swipe, app_on_tick,
app_on_swipe_progress, app_on_touch_down, app_on_touch_move,
};
meow_ui_run(&ev);
meow_view_free(lock);
meow_view_free(settings);
meow_view_free(reader);
meow_view_free(library);
meow_ui_shutdown();
meow_log(MEOW_LOG_INFO, "exit");
return 0;
}