feat: M6.43 — reader分段流式读取(Phase1,只txt) + 面板前台管理/返回回桌面按钮
- reader分段(只txt): core/seg.{h,c} 512KB码位对齐切段(尾字完整)+manifest+按需读单段; book.c rd_book_open只布局每页所在段(治CPU100%/返回无效) load_seg只读当前段(非txt原路径); reader.c 进度实时保存(翻页/刮擦/字号/编码dirty+on_tick节流落盘+退出即时写,锚点存段号,崩溃不丢进度); rdtxt.c fread替代fgetc(去开书扫描卡顿); Phase2(双段拼接+4%释放)留待
- 面板: /api/ams/bg加fg/fg_count(后台保持向后兼容)+POST /api/ams/:pkg/killfg(前台救命:优先am kill,launcher拒则pid直信号SIGTERM->SIGKILL绕过门控)+前端/#/bg前台组'终止'绿徽标+确认弹窗(一键清仍只后台不误杀前台); POST /api/input/gesture(返回=左缘右滑/回桌面=底部上滑,注入滑动轨迹复用SDK手势)+前端屏幕控制页加返回/回桌面MD3按钮
0warning;宿主test_reader_core 72-0/seg_smoke 19-0/loaders_smoke/book_smoke/formats_smoke PASS;面板selftest/node check PASS
This commit is contained in:
1 parent
a64ae06eb6
commit
f40abbd494
17 files changed
+1069
-70
No files matched your search
@@ -1,4 +1,5 @@
|
||||
/* mp_screen.c — 实时画面域:/api/screen.jpeg(fb0→JPEG,增量帧)+ 触摸注入 /api/input/tap。 */
|
||||
/* mp_screen.c — 实时画面域:/api/screen.jpeg(fb0→JPEG,增量帧)+ 触摸注入 /api/input/tap
|
||||
* 与系统手势注入 /api/input/gesture(back=左缘右滑 / home=底部上滑回桌面)。 */
|
||||
#include "mp.h"
|
||||
|
||||
static uint8_t *g_screen_prev = NULL; /* 上一帧紧凑 RGB565 */
|
||||
@@ -6,6 +7,17 @@ static int g_screen_pw = 0, g_screen_ph = 0;
|
||||
static int64_t g_last_self_inject_ms = 0;
|
||||
#define TOUCH_ACTIVE_MS 5000
|
||||
|
||||
/* 手势注入阈值(镜像 meow_ui_input.c / np_gesture.h 系统已识别手势,勿新造语义):
|
||||
* 返回=左缘(起)右移 ≥SWIPE_THRESH 且横向主导;回桌面=底部热区(起)上移 ≥HOME_SWIPE
|
||||
* 且竖向主导 + down_x≥EDGE_W(避左缘返回列)。此处位移留容差(≥65)。 */
|
||||
#define GESTURE_EDGE_W 24 /* 左缘宽度:返回手势起点 x 须 < 此值(meow_ui_input.c EDGE_W) */
|
||||
#define GESTURE_SWIPE_DX 78 /* 返回手势右移位移(≥ SDK SWIPE_THRESH 65,留容差) */
|
||||
#define GESTURE_HOME_EDGE_H 28 /* 底部热区高:回桌面起点 y 须 >= fb_h-此值(HOME_EDGE_H) */
|
||||
#define GESTURE_HOME_DY 80 /* 回桌面手势上移位移(≥ SDK HOME_SWIPE 65,留容差) */
|
||||
#define GESTURE_STEPS 10 /* 线性轨迹插值点数(营造真实滑动轨迹) */
|
||||
#define GESTURE_STEP_MS 12 /* 每步间隔毫秒 */
|
||||
#define GESTURE_HOLD_MS 60 /* 末端按住毫秒再抬起(防 fling 误判) */
|
||||
|
||||
|
||||
int screen_read_frame(const char *dev, uint8_t **out, int *w, int *h)
|
||||
{
|
||||
@@ -230,6 +242,47 @@ int inject_tap(const char *dev, int x, int y)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 线性滑动注入:按下(原点) → 插值移动 → 末端按住 → 抬起。事件序同 inject_tap
|
||||
* (BTN_TOUCH 边沿先于 ABS,goodix 时序免疫;首帧锁原点),设备手势机据此判
|
||||
* 「左缘右滑=返回」或「底部上滑=回桌面」(复用系统已识别信号,不新造)。 */
|
||||
int inject_swipe(const char *dev, int x0, int y0, int x1, int y1)
|
||||
{
|
||||
int fd = open(dev, O_WRONLY);
|
||||
if (fd < 0) return -1;
|
||||
struct input_event ev;
|
||||
#define __WE(t_, c_, v_) do { memset(&ev, 0, sizeof ev); ev.type = (t_); ev.code = (c_); \
|
||||
ev.value = (v_); if (write(fd, &ev, sizeof ev) != (ssize_t)sizeof ev) { close(fd); return -1; } } while (0)
|
||||
/* 按下边沿 + 首帧 ABS 锁原点(与 tap 同序) */
|
||||
__WE(EV_KEY, BTN_TOUCH, 1);
|
||||
__WE(EV_ABS, ABS_MT_SLOT, 0);
|
||||
__WE(EV_ABS, ABS_MT_TRACKING_ID, 7);
|
||||
__WE(EV_ABS, ABS_MT_POSITION_X, x0);
|
||||
__WE(EV_ABS, ABS_MT_POSITION_Y, y0);
|
||||
__WE(EV_ABS, ABS_MT_TOUCH_MAJOR, 6);
|
||||
__WE(EV_ABS, ABS_X, x0);
|
||||
__WE(EV_ABS, ABS_Y, y0);
|
||||
__WE(EV_SYN, SYN_REPORT, 0);
|
||||
/* 插值逐点移动:每步坐标更新 + 同步,营造连续轨迹 */
|
||||
for (int i = 1; i <= GESTURE_STEPS; i++) {
|
||||
int xi = x0 + (x1 - x0) * i / GESTURE_STEPS;
|
||||
int yi = y0 + (y1 - y0) * i / GESTURE_STEPS;
|
||||
__WE(EV_ABS, ABS_MT_POSITION_X, xi);
|
||||
__WE(EV_ABS, ABS_MT_POSITION_Y, yi);
|
||||
__WE(EV_ABS, ABS_X, xi);
|
||||
__WE(EV_ABS, ABS_Y, yi);
|
||||
__WE(EV_SYN, SYN_REPORT, 0);
|
||||
usleep((useconds_t)GESTURE_STEP_MS * 1000);
|
||||
}
|
||||
/* 末端短暂按住再抬起(与 tap 同:抬起到按下边沿被手势机视为一次抬手) */
|
||||
usleep((useconds_t)GESTURE_HOLD_MS * 1000);
|
||||
__WE(EV_KEY, BTN_TOUCH, 0);
|
||||
__WE(EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||
__WE(EV_SYN, SYN_REPORT, 0);
|
||||
#undef __WE
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int api_input_tap(int sock, const req_t *r)
|
||||
{
|
||||
if (!r->body || !r->body[0]) return send_err(sock, 400, "BAD_REQUEST", "缺少 body");
|
||||
@@ -275,3 +328,71 @@ int api_input_tap(int sock, const req_t *r)
|
||||
sbuf_free(&s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* /api/input/gesture:注入设备已识别的系统手势(back=左缘右滑 / home=底部上滑回桌面)。
|
||||
* 复用现有触摸注入通道(/dev/input/event1 滑动轨迹),不触碰被物理键红线禁注入的
|
||||
* /api/key 158/172;由设备自身手势机判成 MEOW_SWIPE_LEFT / MEOW_EV_HOME。 */
|
||||
int api_input_gesture(int sock, const req_t *r)
|
||||
{
|
||||
if (!r->body || !r->body[0]) return send_err(sock, 400, "BAD_REQUEST", "缺少 body");
|
||||
jv_t *root = jv_parse(r->body, (int)r->body_len);
|
||||
if (!root) return send_err(sock, 400, "BAD_REQUEST", "body 非合法 JSON");
|
||||
jv_t *jg = jv_obj_get(root, "gesture");
|
||||
if (!jg || jg->type != J_STR) {
|
||||
jv_free(root);
|
||||
return send_err(sock, 400, "BAD_REQUEST", "缺 gesture(back|home)");
|
||||
}
|
||||
const char *gesture = jg->str;
|
||||
int is_back = (strcmp(gesture, "back") == 0);
|
||||
int is_home = (strcmp(gesture, "home") == 0);
|
||||
jv_free(root);
|
||||
if (!is_back && !is_home)
|
||||
return send_err(sock, 400, "BAD_REQUEST", "gesture 非法(仅 back|home)");
|
||||
|
||||
const char *dev = getenv("MEOW_TOUCH_DEV"); if (!dev || !dev[0]) dev = TOUCH_DEV;
|
||||
const char *fbdev = getenv("MEOW_FB_DEV"); if (!fbdev || !fbdev[0]) fbdev = FB_DEV;
|
||||
int sw = 480, sh = 720;
|
||||
{ int fx = 0, fy = 0; if (fb_dims(fbdev, &fx, &fy) == 0) { sw = fx; sh = fy; } }
|
||||
if (sw < 1) sw = 480;
|
||||
if (sh < 1) sh = 720;
|
||||
|
||||
/* 几何(镜像 SDK 判据 + 留容差,见上 GESTURE_* 宏) */
|
||||
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
|
||||
if (is_back) {
|
||||
x0 = 4; /* 左缘内(< EDGE_W=24) */
|
||||
if (x0 >= sw) x0 = sw - 1;
|
||||
if (x0 >= GESTURE_EDGE_W) x0 = GESTURE_EDGE_W - 1;
|
||||
y0 = y1 = sh / 2; /* 屏中部,避开顶部下拉/底部上滑热区 */
|
||||
x1 = x0 + GESTURE_SWIPE_DX;
|
||||
if (x1 >= sw) x1 = sw - 1; /* 横向主导 + 右移≥阈值 */
|
||||
} else { /* home */
|
||||
x0 = x1 = sw / 2; /* 屏底中部,避开左缘返回列 */
|
||||
if (x0 < GESTURE_EDGE_W) x0 = x1 = GESTURE_EDGE_W;
|
||||
y0 = sh - 2; /* 底部热区(>= fb_h-HOME_EDGE_H) */
|
||||
if (y0 >= sh) y0 = sh - 1;
|
||||
y1 = y0 - GESTURE_HOME_DY;
|
||||
if (y1 < 0) y1 = 0; /* 竖向主导 + 上移≥阈值 */
|
||||
}
|
||||
|
||||
/* 仲裁:本机最近触摸后 5s 内忽略注入(与 tap 同) */
|
||||
int64_t now = now_mono_ms();
|
||||
int64_t last = touch_last_local_ms(dev);
|
||||
if (last > 0 && (now - last) < TOUCH_ACTIVE_MS) {
|
||||
sbuf_t s = {0};
|
||||
sA(&s, "{\"dispatched\":false,\"reason\":\"local_touch_active\",\"cooldown_ms\":%lld}",
|
||||
(long long)(TOUCH_ACTIVE_MS - (now - last)));
|
||||
int ret = send_json(sock, 200, s.b ? s.b : "");
|
||||
sbuf_free(&s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
g_last_self_inject_ms = now_mono_ms();
|
||||
if (inject_swipe(dev, x0, y0, x1, y1) < 0)
|
||||
return send_err(sock, 500, "INTERNAL", "手势注入失败(无法打开触摸设备)");
|
||||
sbuf_t s = {0};
|
||||
sA(&s, "{\"dispatched\":true,\"gesture\":\"%s\",\"from\":[%d,%d],\"to\":[%d,%d]}",
|
||||
gesture, x0, y0, x1, y1);
|
||||
int ret = send_json(sock, 200, s.b ? s.b : "");
|
||||
sbuf_free(&s);
|
||||
return ret;
|
||||
}
|
||||
Reference in new issue
Block a user