Files

176 lines
7.0 KiB
C
Raw Permalink 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 — files 应用装配层:main + 组装 + 事件分发。
*
* 职责(对齐 hello_app/app.c):main 只做初始化/建页/跑事件循环/清理;把 meow_ui_run 的平铺输入
* 回调(key/tap/swipe/tick/touch)路由到当前活动页(browser/viewer);通用长按走独立注册
* (meow_ui_set_long_press_cb,§6.3)路由到 browser。页面切换统一走
* meow_view_page_push/pop(活动栈 + on_enter/on_leave 唯一驱动)。
*
* 铁律(APPS.md §3.4.1 / WORK_STATE.md):物理键禁映射——不处理任何 key 语义;返回=左缘左滑
* (on_swipe LEFT)/返回钮/meow_ui_request_exit。目录进退不换页(browser 改 cur_dir 重扫);
* 文本预览换页(push ACT_VIEWER)。退出=在根目录左滑或 SIGTERM(看门狗)。
*/
#include "files_internal.h"
#include "meow_notify_ipc.h" /* §6.2 二期:picker 结果经 MSG_PICKER_RESULT 回传 */
#include "meow_ipc.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static meow_view *g_browser_view;
static meow_view *g_viewer_view;
static void on_sigterm(int s) { (void)s; meow_ui_request_exit(); }
/* ============================================================ */
/* §6.2 二期:picker 模式(launcher 注入 MEOW_PICKER_* → 选文件返回路径) */
/* ============================================================ */
static char g_picker_action[24];
static char g_picker_caller[MEOW_APP_ID_MAX];
static uint32_t g_picker_req_id;
static int g_picker_active;
int picker_active(void) { return g_picker_active; }
const char *picker_action(void) { return g_picker_action; }
uint32_t picker_req_id(void) { return g_picker_req_id; }
static void picker_init(void)
{
const char *a = getenv("MEOW_PICKER_ACTION");
if (!a || !a[0]) return;
snprintf(g_picker_action, sizeof g_picker_action, "%s", a);
g_picker_active = 1;
const char *c = getenv("MEOW_PICKER_CALLER");
if (c) snprintf(g_picker_caller, sizeof g_picker_caller, "%s", c);
const char *r = getenv("MEOW_PICKER_REQ_ID");
g_picker_req_id = r ? (uint32_t)atoi(r) : 0;
meow_log(MEOW_LOG_INFO, "picker: mode action=%s req=%u caller=%s",
g_picker_action, g_picker_req_id, g_picker_caller);
}
/* 选文件:发 MSG_PICKER_RESULT(OK+路径)+ 请求退出。best-effort(launcher 不在静默)。 */
void picker_return_file(const char *path)
{
m_picker_result_t r;
memset(&r, 0, sizeof r);
snprintf(r.caller, sizeof r.caller, "%s", g_picker_caller);
r.req_id = g_picker_req_id;
snprintf(r.action, sizeof r.action, "%s", g_picker_action);
r.code = MEOW_OK;
if (path) snprintf(r.value, sizeof r.value, "%s", path);
(void)meow_notify_ipc_send_raw(MSG_PICKER_RESULT, &r, (uint32_t)sizeof r, 1);
meow_log(MEOW_LOG_INFO, "picker: return path=%s", path ? path : "");
meow_ui_request_exit();
}
/* 取消:发 MSG_PICKER_RESULT(MEOW_ERR_NOENT+空值)+ 请求退出。 */
void picker_cancel(void)
{
m_picker_result_t r;
memset(&r, 0, sizeof r);
snprintf(r.caller, sizeof r.caller, "%s", g_picker_caller);
r.req_id = g_picker_req_id;
snprintf(r.action, sizeof r.action, "%s", g_picker_action);
r.code = MEOW_ERR_NOENT; /* 用户取消 */
(void)meow_notify_ipc_send_raw(MSG_PICKER_RESULT, &r, (uint32_t)sizeof r, 1);
meow_log(MEOW_LOG_INFO, "picker: cancel");
meow_ui_request_exit();
}
/* ============================================================ */
/* 事件分发:meow_ui_run 平铺回调 → 当前页 */
/* ============================================================ */
/* 物理键系统语义(息屏/音量/媒体)由 SDK 消化;App 不映射(§3.4.1)。 */
static void app_on_key(int keycode, int is_down)
{
(void)keycode; (void)is_down;
}
static void app_on_tap(int x, int y)
{
if (viewer_is_active()) { viewer_on_tap(x, y); return; }
if (browser_is_active()) { browser_on_tap(x, y); return; }
}
static void app_on_swipe(int dir, int dx, int dy)
{
(void)dx;
if (dir == MEOW_SWIPE_LEFT) {
/* 左缘返回:预览页→回目录;浏览器→上级目录;到根→退出 App(picker 模式则取消)。 */
if (viewer_is_active()) { meow_view_page_pop(); return; }
if (browser_is_active() && browser_go_up()) return;
if (picker_active()) { picker_cancel(); return; } /* §6.2 二期:根屏左滑=取消 picker */
meow_log(MEOW_LOG_INFO, "exit:swipe");
meow_ui_request_exit();
return;
}
if (viewer_is_active()) { viewer_swipe(dir, dy); return; }
if (browser_is_active()) { browser_swipe(dir, dy); return; }
}
/* 左缘返回手势过程视觉条(SDK 自动画顶部进度条,App 转发)。 */
static void app_on_swipe_progress(int x_start, int dx)
{
meow_ui_swipe_hint(x_start + dx);
}
/* 拖拽过程(跟手):列表/文本内容滚动。 */
static void app_on_touch_down(int x, int y)
{
if (viewer_is_active()) viewer_touch_down(x, y);
else if (browser_is_active()) browser_touch_down(x, y);
}
static void app_on_touch_move(int x, int y)
{
if (viewer_is_active()) viewer_touch_move(x, y);
else if (browser_is_active()) browser_touch_move(x, y);
}
/* 通用长按(§6.3):SDK 判定「按下 ≥ 阈值未抬手且位移 ≤ 容忍」后带坐标回调;
* browser 据此行命中打开 BottomSheet。viewer 无长按语义。 */
static void app_on_long_press(int x, int y)
{
if (browser_is_active()) browser_on_long_press(x, y);
}
/* on_tick:本 App 无帧动画/时钟(长按计时已下沉 SDK §6.3),保留为空槽。 */
static void app_on_tick(void) { }
/* ============================================================ */
/* main */
/* ============================================================ */
int main(void)
{
meow_log(MEOW_LOG_INFO, "start");
meow_ui_opts o = { APP_W, APP_H };
if (meow_ui_init(&o) != 0) { meow_log(MEOW_LOG_ERROR, "init failed"); return 1; }
meow_theme_add_listener(NULL);
signal(SIGTERM, on_sigterm);
picker_init(); /* §6.2 二期:读 MEOW_PICKER_* 决定是否进入 picker 模式 */
/* 建两页 view(on_create 建各自控件/状态 + 读卡扫首个目录) */
g_browser_view = browser_view_create();
g_viewer_view = viewer_view_create();
/* 进入根页(ACT_BROWSER = 目录浏览;默认卡根 /usr/data/mnt/sd_0) */
meow_view_page_push(ACT_BROWSER);
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,
};
/* 通用长按走独立注册(§6.3):不进 meow_ui_events(避免位置初始化在 -Wextra 下告警)。 */
meow_ui_set_long_press_cb(app_on_long_press);
meow_ui_run(&ev);
/* 清理:meow_view_free 触发各页 on_destroy(控件 + 文本缓冲) */
meow_view_free(g_viewer_view);
meow_view_free(g_browser_view);
meow_ui_shutdown();
meow_log(MEOW_LOG_INFO, "exit");
return 0;
}