feat: M6.10–M6.19 批量收编 + M6.19 推卡验收
- M7 launcher 重写 5 期(虚拟化宫格/meow_theme 单一权威/横幅动画/自定义 PIN 键盘) - OOM 通用化(cachegov 上收 SDK)、自动切歌根治、meowpanel jv_free 泄漏修复、Hello 滚动卡顿修复 - ncm 歌词 UI / 媒体通知封面 / 封面分辨率 640 - 5 bug 修复:ncm 后台化 UI 叠层+点击穿透、再进 ncm 桌面叠层、播放页新旧 UI 叠层抢刷脏区(meow_ui_gfx 恢复边沿整帧重画)、PIN 亮屏亮度跳(keys.c meow_panel_on 按 settings_brightness_clamped 恢复)、通知中心封面显歌单封面(cover.c save_cover_raw 加 is_song + 命中块守卫) - 四 App 统一重链新 meow_ui.a 51caee4a;M6.19=0.8.19 固件 2d2331f2 推卡自刷验收全绿
This commit is contained in:
1 parent
c2ee7626a4
commit
3d70a3dd2c
176 files changed
+15507
-597
No files matched your search
@@ -38,6 +38,16 @@ static const int lk_keys[LK_ROWS][LK_COLS] = {
|
||||
{ LK_ACT_CLR, 0, LK_ACT_BS },
|
||||
};
|
||||
|
||||
/* ---- M7.1b 锁屏控件化:PIN 数字键盘 / 时钟 / 提示 / PIN 圆点 改用 SDK 控件 ----
|
||||
* 旧自绘锁屏 UI 保留在 #if 0(回退位,见 lk_draw/lk_key_hit),新 SDK 渲染默认启用;
|
||||
* run_lock_screen 会话骨架(EVIOCGRAB / 自睡 / 解锁脏区修复 / 物理键转发)不动,只替换
|
||||
* 它调用的绘制/命中函数体。控件 owner 钉 LK_SENTINEL_ACT(子页 0x52 之外的独立哨兵)。 */
|
||||
#define LK_SENTINEL_ACT 0x51 /* 锁屏控件 owner 哨兵(与子页 SUB_SENTINEL_ACT=0x52 区分) */
|
||||
#define LK_DOWN_NONE (-10) /* 无键按下哨兵(关键值范围 LK_ACT_CLR=-2/-1/0-9) */
|
||||
static meow_widget *lk_key_w[LK_ROWS][LK_COLS]; /* 12 键按钮(meow_widget_custom) */
|
||||
static int lk_widgets_ready = 0;
|
||||
static int g_lk_down_key = LK_DOWN_NONE; /* 当前按下的键(跟手指按压态) */
|
||||
|
||||
/* 键盘按钮 row*3+col 的命中矩形(x,y,w,h) */
|
||||
static void lk_key_rect(int row, int col, int *x, int *y, int *w, int *h)
|
||||
{
|
||||
@@ -79,6 +89,121 @@ static void lk_draw_pin(int entered, const meow_ui_theme_t *th)
|
||||
lk_pin_dot(x0 + i * gap, y, r, i < entered, th->primary, th->surface);
|
||||
}
|
||||
|
||||
/* ---- M7.1b 控件化:SDK meow_widget 键盘 + meow_font 文字 ---- */
|
||||
|
||||
/* 数字键标签(1-9/0 单字符;static 缓冲各调用立即消费,无跨调用残留) */
|
||||
static const char *lk_key_digit(int key)
|
||||
{
|
||||
static char d[2];
|
||||
d[0] = (char)('0' + key);
|
||||
d[1] = 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
/* 键渲染:surfaceContainer 圆角底(MD3)+ 按压态 primary 26% α + 居中标签(SDK meow_font)。
|
||||
* 颜色全部取 meow_theme_get()(SDK 单一权威:MD3/MIUIx × 明暗自动);读 w->state 的
|
||||
* MEOW_WS_PRESSED 位(跟手指,由 lk_set_down_key 置/清)。 */
|
||||
static void lk_key_render(meow_widget *w, const meow_theme *th, void *ctx)
|
||||
{
|
||||
int key = (int)(intptr_t)ctx;
|
||||
int rc[4]; meow_widget_rect(w, rc); /* 绝对坐标 x,y,w,h(控件不透明,用 SDK 只读几何) */
|
||||
int x = rc[0], y = rc[1], ww = rc[2], hh = rc[3];
|
||||
unsigned st = meow_widget_state(w);
|
||||
int rad = (th->radius > 0) ? th->radius : 10;
|
||||
meow_gfx_fill_round(x, y, ww, hh, rad, th->surfaceContainer);
|
||||
if (st & MEOW_WS_PRESSED)
|
||||
meow_gfx_fill_round_alpha(x, y, ww, hh, rad, th->primary, 66);
|
||||
const char *label;
|
||||
int size;
|
||||
if (key >= 0) { size = 30; label = lk_key_digit(key); }
|
||||
else if (key == LK_ACT_CLR) { size = 22; label = mfont_ready ? "清空" : "C"; }
|
||||
else { size = 22; label = mfont_ready ? "退格" : "DEL"; }
|
||||
int cx = x + ww / 2;
|
||||
int cy = y + hh / 2 - meow_ui_text_height(size) / 2;
|
||||
meow_ui_text_center(cx, cy, label, size, th->onSurface);
|
||||
}
|
||||
|
||||
/* 懒创建 12 键(owner=LK_SENTINEL_ACT;仅首次调用建一次)。布局几何沿用 lk_key_rect。 */
|
||||
static void lk_widgets_build(void)
|
||||
{
|
||||
if (lk_widgets_ready) return;
|
||||
meow_ui_activity_push(LK_SENTINEL_ACT);
|
||||
for (int r = 0; r < LK_ROWS; r++) {
|
||||
for (int c = 0; c < LK_COLS; c++) {
|
||||
int x, y, w, h; lk_key_rect(r, c, &x, &y, &w, &h);
|
||||
lk_key_w[r][c] = meow_widget_custom_create(x, y, w, h, lk_key_render, NULL,
|
||||
(void *)(intptr_t)lk_keys[r][c]);
|
||||
}
|
||||
}
|
||||
meow_ui_activity_pop();
|
||||
lk_widgets_ready = 1;
|
||||
}
|
||||
|
||||
/* 键值 -> 按钮(按压态置/清位用)。 */
|
||||
static meow_widget *lk_widget_for_key(int key)
|
||||
{
|
||||
for (int r = 0; r < LK_ROWS; r++)
|
||||
for (int c = 0; c < LK_COLS; c++)
|
||||
if (lk_keys[r][c] == key) return lk_key_w[r][c];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 坐标 -> 键值(SDK meow_widget_hit;owner==active 已由调用方保证)。未命中返回 LK_DOWN_NONE。 */
|
||||
static int lk_key_value_at(int x, int y)
|
||||
{
|
||||
for (int r = 0; r < LK_ROWS; r++)
|
||||
for (int c = 0; c < LK_COLS; c++)
|
||||
if (lk_key_w[r][c] && meow_widget_hit(lk_key_w[r][c], x, y))
|
||||
return lk_keys[r][c];
|
||||
return LK_DOWN_NONE;
|
||||
}
|
||||
|
||||
/* 更新按压态(跟手指):清旧键状态位、置新键;返回 1=按键变化(调用方据此重绘)。 */
|
||||
static int lk_set_down_key(int key)
|
||||
{
|
||||
if (key == g_lk_down_key) return 0;
|
||||
meow_widget *old = lk_widget_for_key(g_lk_down_key);
|
||||
if (old) meow_widget_set_state(old, MEOW_WS_PRESSED, 0);
|
||||
meow_widget *nw = lk_widget_for_key(key);
|
||||
if (nw) meow_widget_set_state(nw, MEOW_WS_PRESSED, 1);
|
||||
g_lk_down_key = key;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* PIN 输入圆点(● 遮罩:已输入=primary 实心;未输入=primary 环 + surface 孔)。 */
|
||||
static void lk_draw_pin_dots(int entered, const meow_theme *mt)
|
||||
{
|
||||
int cx = fb_xres / 2;
|
||||
int y = 210;
|
||||
int gap = 48, r = 20;
|
||||
int x0 = cx - (3 * gap) / 2;
|
||||
for (int i = 0; i < LCK_PIN_LEN; i++) {
|
||||
int dx = x0 + i * gap;
|
||||
fill_circle(dx, y, r, mt->primary);
|
||||
if (i >= entered) fill_circle(dx, y, r - 3, mt->surface);
|
||||
}
|
||||
}
|
||||
|
||||
/* 键命中:旧自绘(lk_key_rect+mt_in)保留在 #if 0(回退位);M7.1b 走 SDK meow_widget_hit
|
||||
* (owner==active + enabled 双闸门在 SDK 内;命中点=按下原点 mt->down_x/down_y,与原 mt_in 同源)。 */
|
||||
#if 0
|
||||
static int lk_key_hit(const meow_touch *mt, int row, int col)
|
||||
{
|
||||
int x, y, w, h; lk_key_rect(row, col, &x, &y, &w, &h);
|
||||
return mt_in(mt, x, y, w, h);
|
||||
}
|
||||
#else
|
||||
static int lk_key_hit(const meow_touch *mt, int row, int col)
|
||||
{
|
||||
if (!lk_key_w[row][col]) return 0;
|
||||
return meow_widget_hit(lk_key_w[row][col], mt->down_x, mt->down_y);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* ============ 旧自绘锁屏整帧(M7.1b 回退位)============
|
||||
* 原 lk_draw:fill_rect 全屏底 + lk_text(时钟/状态)+ lk_draw_pin(●)+ fill_round_rect 键盘。
|
||||
* 一键回退:把下面 #if 0 改成 #if 1(并把新 lk_draw 的 #else 分支由 #else 改走旧轮廓),设备即回旧观感。 */
|
||||
static void lk_draw(int entered, const char *status, time_t locked_until)
|
||||
{
|
||||
const meow_ui_theme_t *th = s_ui_theme();
|
||||
@@ -116,6 +241,36 @@ static void lk_draw(int entered, const char *status, time_t locked_until)
|
||||
fb_pan_buf0_force();
|
||||
meow_ui_flush();
|
||||
}
|
||||
#else
|
||||
/* ============ M7.1b 锁屏控件化整帧(默认启用)============
|
||||
* 整帧不透明 surface 底(§310 脏区修复关键:全屏覆盖,无 App 帧透出)+ SDK 字体时钟/提示
|
||||
* + 主题色 PIN 圆点 + meow_widget 键盘(surfaceContainer 圆角 / 按压态 primary 26% α / MD3 主题)。
|
||||
* 颜色全部取 meow_theme_get()(SDK 单一权威:MD3/MIUIx × 明暗自动)。 */
|
||||
static void lk_draw(int entered, const char *status, time_t locked_until)
|
||||
{
|
||||
const meow_theme *mt = meow_theme_get();
|
||||
meow_ui_fill_rect(0, 0, fb_xres, fb_yres, mt->surface); /* 全屏不透明表面底 */
|
||||
lk_widgets_build(); /* 懒创建 12 键 */
|
||||
/* 时钟/提示(居中,SDK meow_font):锁定倒计时标题 */
|
||||
meow_ui_text_center(fb_xres / 2, 120, locked_until > 0 ? "已锁定" : "输入 PIN 解锁",
|
||||
24, mt->onSurface);
|
||||
/* PIN 输入圆点(● 遮罩) */
|
||||
lk_draw_pin_dots(entered, mt);
|
||||
/* 状态行:错误提示(PIN 错误)着 error;倒计时/其它信息用 onSurfaceVariant */
|
||||
int is_err = status[0] && (strstr(status, "PIN 错误") != NULL ||
|
||||
strstr(status, "WRONG PIN") != NULL);
|
||||
uint32_t status_col = status[0] ? (is_err ? mt->error : mt->onSurfaceVariant)
|
||||
: mt->onSurfaceVariant;
|
||||
meow_ui_text_center(fb_xres / 2, 260, status, 18, status_col);
|
||||
/* 12 键(SDK meow_widget;命中走 lk_key_hit → meow_widget_hit) */
|
||||
for (int r = 0; r < LK_ROWS; r++)
|
||||
for (int c = 0; c < LK_COLS; c++)
|
||||
if (lk_key_w[r][c]) meow_widget_draw(lk_key_w[r][c]);
|
||||
meow_dirty_full();
|
||||
fb_pan_buf0_force();
|
||||
meow_ui_flush();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 阻塞式锁屏页。返回 1=已解锁,0=锁屏期间电源键息屏。 */
|
||||
int run_lock_screen(void)
|
||||
@@ -159,7 +314,26 @@ int run_lock_screen(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
lk_draw(entered, status, lock_until); /* 首帧(fill_rect 全屏不透明主题底 + 键盘) */
|
||||
/* M7.1 解锁恢复:锁屏是整帧不透明覆盖(lk_draw fill_rect 全屏),退出后底层界面不会自动重绘
|
||||
* —— 只有 App 自绘的控件区域刷新,未刷新区残留锁屏 PIN 最后一帧(解锁后整屏脏区根因)。此处
|
||||
* 在锁屏首扑前把底层帧(SDK back_buf = 进入前的 App 帧/主界面帧)快照下来;解锁(unlocked=1)
|
||||
* 时整帧回写 back_buf + present,强制底层界面完整重绘(app_launcher.c 的 lock-overlay 关闭路径
|
||||
* 随后 pm_capture_app_frame 读 fb0 即得到正确 App 帧,不再读到锁帧)。 */
|
||||
unsigned char *lk_bg_snap = NULL;
|
||||
size_t lk_bg_len = 0;
|
||||
if (back_buf_ok && fb && fb_line > 0 && fb_yres > 0) {
|
||||
lk_bg_len = (size_t)fb_line * (size_t)fb_yres;
|
||||
lk_bg_snap = malloc(lk_bg_len);
|
||||
if (lk_bg_snap) memcpy(lk_bg_snap, fb, lk_bg_len);
|
||||
else { lk_bg_len = 0; logmsg("lock: bg snapshot malloc fail (len=%zu)", lk_bg_len); }
|
||||
}
|
||||
|
||||
/* M7.1b:锁屏控件 owner 闸门打开(meow_widget_hit / 按压态需 active==LK_SENTINEL_ACT)。
|
||||
* 会话骨架(EVIOCGRAB/自睡/解锁脏区修复)不受影响;done/died 处对称 pop。 */
|
||||
meow_ui_activity_push(LK_SENTINEL_ACT);
|
||||
g_lk_down_key = LK_DOWN_NONE;
|
||||
|
||||
lk_draw(entered, status, lock_until); /* 首帧(全屏不透明主题底 + 控件化键盘) */
|
||||
|
||||
int unlocked = 0;
|
||||
unsigned long long entry_ms = now_ms();
|
||||
@@ -173,6 +347,9 @@ int run_lock_screen(void)
|
||||
unsigned long long last_act = now_ms();
|
||||
int asleep = 0;
|
||||
int prev_pwr_down = 0;
|
||||
/* M7.1 锁屏期物理键保留语义(音量/媒体键):边沿跟踪基线(锁屏是 EVIOCGRAB 独占真模态,
|
||||
* 这些键只能在本层显式处理,不会转发到系统)。 */
|
||||
int prev_vold = 0, prev_volu = 0, prev_play = 0, prev_prv = 0, prev_nxt = 0;
|
||||
for (;;) {
|
||||
time_t now = time(NULL);
|
||||
int redraw = 0;
|
||||
@@ -246,6 +423,7 @@ int run_lock_screen(void)
|
||||
meow_panel_on();
|
||||
asleep = 0;
|
||||
last_act = now_ms();
|
||||
g_lk_down_key = LK_DOWN_NONE; /* M7.1b:唤醒复位按压态基线 */
|
||||
lk_draw(entered, status, lock_until); /* 重画锁屏页回锁 */
|
||||
continue;
|
||||
}
|
||||
@@ -256,6 +434,50 @@ int run_lock_screen(void)
|
||||
meow_panel_off();
|
||||
break; /* return 0 */
|
||||
}
|
||||
/* M7.1 锁屏期物理键仍执行其语义(用户定案:音量键调音量、媒体键控播放/上下曲)。
|
||||
* 锁屏层 EVIOCGRAB 独占这些输入(真模态),不转发系统,故必须在此显式处理,不能依赖别处。
|
||||
* 音量沿用 launcher 既有递增/递减路径(settings_volume_adj —— 起 1% 线性渐变,
|
||||
* 长按由下方 vol_ramp_tick 每圈推进);播放/上下曲经 meow_media_playctl 下发媒体指令。 */
|
||||
int vold = (kp_keys.ok) && kp_is_down(&kp_keys, KEY_VOLUMEDOWN);
|
||||
int volu = (kp_keys.ok) && kp_is_down(&kp_keys, KEY_VOLUMEUP);
|
||||
int play = (kp_keys.ok) && kp_is_down(&kp_keys, KEY_PLAYPAUSE);
|
||||
int prv = (kp_keys.ok && kp_is_down(&kp_keys, KEY_PREVIOUSSONG)) ||
|
||||
(kp_power.ok && kp_is_down(&kp_power, KEY_PREVIOUSSONG));
|
||||
int nxt = (kp_keys.ok && kp_is_down(&kp_keys, KEY_NEXT)) ||
|
||||
(kp_power.ok && kp_is_down(&kp_power, KEY_NEXT));
|
||||
if (vold && !prev_vold) { settings_volume_adj(-settings_volume_step); last_act = now_ms(); }
|
||||
if (volu && !prev_volu) { settings_volume_adj(+settings_volume_step); last_act = now_ms(); }
|
||||
if (play && !prev_play) {
|
||||
const meow_media_session_t *ms = meow_media_current();
|
||||
if (ms) {
|
||||
uint32_t c = (ms->state == MEOW_MEDIA_PLAYING) ? 2u : 1u; /* 暂停/播放 */
|
||||
int rc = meow_media_playctl(c, 0);
|
||||
logmsg("lock: play key -> media cmd=%u rc=%d (%s)", c, rc, ms->app_id);
|
||||
} else {
|
||||
logmsg("lock: play key -> media-reserved (no media source)");
|
||||
}
|
||||
last_act = now_ms();
|
||||
}
|
||||
if (prv && !prev_prv) {
|
||||
if (meow_media_current()) { int rc = meow_media_playctl(3, 0); logmsg("lock: prev key -> cmd=3 rc=%d", rc); }
|
||||
else logmsg("lock: prev key -> media-reserved (no media source)");
|
||||
last_act = now_ms();
|
||||
}
|
||||
if (nxt && !prev_nxt) {
|
||||
if (meow_media_current()) { int rc = meow_media_playctl(4, 0); logmsg("lock: next key -> cmd=4 rc=%d", rc); }
|
||||
else logmsg("lock: next key -> media-reserved (no media source)");
|
||||
last_act = now_ms();
|
||||
}
|
||||
prev_vold = vold; prev_volu = volu; prev_play = play; prev_prv = prv; prev_nxt = nxt;
|
||||
/* 长按音量键线性渐变(同主菜单 vol_ramp 路径,每圈推进 1%)。锁屏态不刷状态栏
|
||||
* (状态栏被锁屏页覆盖),仅保持真实音量/DAC 同步。 */
|
||||
if (vol_ramp_dir != 0) {
|
||||
int held = (vol_ramp_dir > 0)
|
||||
? (kp_keys.ok && kp_is_down(&kp_keys, KEY_VOLUMEUP))
|
||||
: (kp_keys.ok && kp_is_down(&kp_keys, KEY_VOLUMEDOWN));
|
||||
int going = vol_ramp_tick(held);
|
||||
if (!going) logmsg("lock: volume ramp end -> %d", settings_volume_get());
|
||||
}
|
||||
/* 空闲超时 → 自睡(锁态保持,仍在锁屏循环,唤醒回锁屏页) */
|
||||
if (meow_screen_on && now_ms() - last_act >= lk_off_ms) {
|
||||
logmsg("lock: idle %ds -> self screen off (stay locked)", lk_off_sec);
|
||||
@@ -265,8 +487,6 @@ int run_lock_screen(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
(void)kp_is_down(&kp_keys, KEY_VOLUMEDOWN);
|
||||
(void)kp_is_down(&kp_keys, KEY_VOLUMEUP);
|
||||
|
||||
/* 触摸:只认键盘 tap(滑动手势忽略:不左缘返回、不通知中心下拉);触摸即输入活动,重置自睡计时 */
|
||||
if (tfd >= 0 && !asleep) {
|
||||
@@ -280,17 +500,24 @@ int run_lock_screen(void)
|
||||
if (type == EV_ABS) {
|
||||
if (code == ABS_X || code == ABS_MT_POSITION_X) mt_abs(&mt, val, mt.last_y);
|
||||
else if (code == ABS_Y || code == ABS_MT_POSITION_Y) mt_abs(&mt, mt.last_x, val);
|
||||
/* M7.1b 跟手指按压态:down 且两轴有效才定键(goodix 时序免疫);
|
||||
* 键变化(滑动换键)即时重绘按压高亮。 */
|
||||
if (mt.down && mt.last_x >= 0 && mt.last_y >= 0) {
|
||||
if (lk_set_down_key(lk_key_value_at(mt.last_x, mt.last_y)))
|
||||
redraw = 1;
|
||||
}
|
||||
} else if (type == EV_KEY && code == BTN_TOUCH) {
|
||||
if (val && !mt.down) {
|
||||
mt_down(&mt);
|
||||
} else if (!val && mt.down) {
|
||||
lk_set_down_key(LK_DOWN_NONE); /* M7.1b:抬手清按压态 */
|
||||
redraw = 1;
|
||||
int dx, dy;
|
||||
if (mt_up(&mt, &dx, &dy)) {
|
||||
int handled = 0;
|
||||
for (int r = 0; r < LK_ROWS && !handled; r++) {
|
||||
for (int c = 0; c < LK_COLS && !handled; c++) {
|
||||
int x, y, w, h; lk_key_rect(r, c, &x, &y, &w, &h);
|
||||
if (!mt_in(&mt, x, y, w, h)) continue;
|
||||
if (!lk_key_hit(&mt, r, c)) continue; /* M7.1b SDK 控件命中 */
|
||||
handled = 1;
|
||||
int key = lk_keys[r][c];
|
||||
if (lock_until > 0) break; /* 锁定期间键盘不响应 */
|
||||
@@ -339,6 +566,17 @@ int run_lock_screen(void)
|
||||
usleep(POLL_MS * 1000);
|
||||
}
|
||||
done:
|
||||
meow_ui_activity_pop(); /* M7.1b:锁屏控件 owner 闸门关闭(与进场 push 对称) */
|
||||
g_lk_down_key = LK_DOWN_NONE;
|
||||
/* M7.1 解锁恢复:把锁屏首扑前快照的底层帧整帧回写 back_buf + present,强制底层 App/主界面
|
||||
* 完整重绘(消除「解锁后整屏 = PIN 最后一帧,仅 App 控件自绘区刷新」的脏区残留)。 */
|
||||
if (unlocked && lk_bg_snap && back_buf_ok && fb && lk_bg_len > 0) {
|
||||
memcpy(fb, lk_bg_snap, lk_bg_len);
|
||||
meow_dirty_full();
|
||||
meow_ui_flush();
|
||||
logmsg("lock: unlock -> restore underlying frame (full repaint)");
|
||||
}
|
||||
if (lk_bg_snap) { free(lk_bg_snap); lk_bg_snap = NULL; lk_bg_len = 0; }
|
||||
if (tfd >= 0) {
|
||||
int grab = 0; /* 显式释放 EVIOCGRAB(关闭 tfd 也会自动解除,双保险) */
|
||||
ioctl(tfd, EVIOCGRAB, &grab);
|
||||
@@ -349,6 +587,9 @@ done:
|
||||
logmsg("lock: exit unlocked=%d screen_on=%d", unlocked, meow_screen_on);
|
||||
return unlocked;
|
||||
died:
|
||||
meow_ui_activity_pop(); /* M7.1b:锁屏控件 owner 闸门关闭(与进场 push 对称) */
|
||||
g_lk_down_key = LK_DOWN_NONE;
|
||||
if (lk_bg_snap) { free(lk_bg_snap); lk_bg_snap = NULL; lk_bg_len = 0; }
|
||||
if (tfd >= 0) {
|
||||
int grab = 0;
|
||||
ioctl(tfd, EVIOCGRAB, &grab);
|
||||
|
||||
Reference in new issue
Block a user