launcher(M7.0b): 电源菜单/Now Playing 控件化 + SDK 主题薄壳 + i18n 抽取(试点迁移)
M7 整体 MD3 重写试点(M7.0 定两隔离页,只动 patch_v2/meow_launcherd/): - 电源菜单 power_menu.c:圆角卡→meow_card;6 圆钮→meow_iconbtn(回HiBy=ARROW_BACK、 取消=CLOSE;sb_icons 表在位图)+ meow_widget_custom_create(关机/重启/升级/锁定=pm_icons 专有,圆形命中自定义);命中/选中/按压态全走 SDK(meow_widget_hit/set_state/draw), 触摸按下置 PRESSED、抬起清(pm_blend 按主题混合状态层);py 手动驱动控件(哨兵 activity 0x50 push/pop,owner 闸门使命中生效)。 - Now Playing now_playing.c:进度条→meow_progress;播放控制三钮→meow_iconbtn(SKIP_PREV / PLAY_ARROW|PAUSE同位双钮按状态只画其一/ SKIP_NEXT);命中走 meow_widget_hit;封面 (meow_img contain) 与歌名/艺术家 (meow_font) 保留;哨兵 activity 0x51 push/pop。 - 主题薄壳 font_theme.c:s_ui_theme() 改读 SDK meow_theme_export()(单一权威,9 字段映射 §8.1.5),退役 launcher 自持 4 套静态色板(#if 0 回退位)。 - i18n 抽取:两页硬编码中文案改 meow_str(新增 meow_str_zh 辅助:SDK 内嵌表无 launcher 域串 时回退中文默认,TF 覆盖表/后续并入 SDK 内嵌后自动换语)。 - 会话骨架不动:物理键语义(单击息屏/3s 菜单/8s 强关/左缘返回/横划 NP)与两页进入退出/事件流 未改,只替换「怎么画/怎么命中」;旧绘制函数 #if 0 留回退位。 - 验证:新增 test_power_menu_widgets / test_now_playing_widgets 宿主测试(圆形命中/owner+enabled 闸门/选中按压态像素/主题四态 MD3+MIUIx×明暗 渲染 + meow_theme_export 九字段)全 PASS; launcher 全量宿主回归(lock_screen/overlay_gate/utf8_name/media/depends/ams_start/bgplay/ settings_brightness/netmgr_ipc/vol_ramp_jack/notif_panel/notif_tf/lock_render + SDK theme_export/ iconbtn)全 PASS;交叉 -Wall -Wextra 0 warning。新 meow_launcherd md5 94a33b7b。
This commit is contained in:
1 parent
a8c51be1fc
commit
d8241cd2d6
7 files changed
+774
-79
No files matched your search
@@ -47,6 +47,10 @@ static void np_cover_load(const meow_media_session_t *s)
|
||||
g_np_cover = meow_img_load_file(path);
|
||||
}
|
||||
|
||||
#if 0 /* ================================================================
|
||||
* M7.0b 退役:Now Playing 手绘控制钮/进度条改走 SDK 控件(meow_iconbtn +
|
||||
* meow_progress),命中/状态/进度全由 SDK 接管;保留作回退位(删除 #if 0 行恢复旧手绘)。
|
||||
* ================================================================ */
|
||||
/* 实心三角(dir=+1 右向 / -1 左向)。 */
|
||||
static void np_tri(int cx, int cy, int size, int dir, uint32_t col)
|
||||
{
|
||||
@@ -59,25 +63,6 @@ static void np_tri(int cx, int cy, int size, int dir, uint32_t col)
|
||||
}
|
||||
}
|
||||
|
||||
/* 居中 + 按宽截断(UTF-8 安全),防超长标题溢出屏外。 */
|
||||
static void np_center_text(int y, const char *s, int size, uint32_t color, int maxw)
|
||||
{
|
||||
if (!s) s = "";
|
||||
int W = fb_xres;
|
||||
if (ui_width(s, size) <= maxw) {
|
||||
ui_draw((W - ui_width(s, size)) / 2, y, s, color, size);
|
||||
return;
|
||||
}
|
||||
/* 近似截断:实际按字节长度比例切(title/artist 罕见超长,够用不裂屏) */
|
||||
char buf[160];
|
||||
int keep = (int)(strlen(s) * maxw / (ui_width(s, size) + 1));
|
||||
if (keep < 0) keep = 0;
|
||||
if (keep > (int)sizeof buf - 4) keep = (int)sizeof buf - 4;
|
||||
memcpy(buf, s, (size_t)keep); buf[keep] = 0;
|
||||
strcat(buf, "...");
|
||||
ui_draw((W - ui_width(buf, size)) / 2, y, buf, color, size);
|
||||
}
|
||||
|
||||
/* 圆形控制按钮(kind:0=prev 1=play 2=next 3=pause)。 */
|
||||
static void np_btn(int cx, int cy, int r, int kind, const meow_ui_theme_t *th)
|
||||
{
|
||||
@@ -97,14 +82,94 @@ static void np_btn(int cx, int cy, int r, int kind, const meow_ui_theme_t *th)
|
||||
fill_rect(cx + 8 - bw, cy - (r - 7), bw, (r - 7) * 2, fg);
|
||||
}
|
||||
}
|
||||
#endif /* M7.0b 退役:Now Playing 旧手绘控制钮 */
|
||||
|
||||
/* 进度带(进度条 + 时间)绘制;pts = 当前显示位置。 */
|
||||
/* 居中 + 按宽截断(UTF-8 安全),防超长标题溢出屏外。(M7.0b 保留:封面/歌名/艺术家仍 SD) */
|
||||
static void np_center_text(int y, const char *s, int size, uint32_t color, int maxw)
|
||||
{
|
||||
if (!s) s = "";
|
||||
int W = fb_xres;
|
||||
if (ui_width(s, size) <= maxw) {
|
||||
ui_draw((W - ui_width(s, size)) / 2, y, s, color, size);
|
||||
return;
|
||||
}
|
||||
/* 近似截断:实际按字节长度比例切(title/artist 罕见超长,够用不裂屏) */
|
||||
char buf[160];
|
||||
int keep = (int)(strlen(s) * maxw / (ui_width(s, size) + 1));
|
||||
if (keep < 0) keep = 0;
|
||||
if (keep > (int)sizeof buf - 4) keep = (int)sizeof buf - 4;
|
||||
memcpy(buf, s, (size_t)keep); buf[keep] = 0;
|
||||
strcat(buf, "...");
|
||||
ui_draw((W - ui_width(buf, size)) / 2, y, buf, color, size);
|
||||
}
|
||||
|
||||
/* ==================================================================
|
||||
* M7.0b Now Playing 控件化(launcher 无 meow_ui_run,手动驱动 SDK 控件):
|
||||
* - 进度条 → meow_progress(线性,SDK 主题 track/fill);
|
||||
* - 播放控制三钮 → meow_iconbtn(PREV / PLAY_ARROW|PAUSE / NEXT;按下=PAUSE、暂停=PLAY_ARROW,
|
||||
* 同位置叠两钮、按当前状态只画其一);
|
||||
* - 命中走 meow_widget_hit(圆形,owner==哨兵 + enabled 闸门)→ meow_media_playctl 分发;
|
||||
* - 封面(meow_img contain)与歌名/艺术家(meow_font)不动(本就 SD),仅文案走 meow_str。
|
||||
* 控件 lazy 创建一次(owner=NP_SENTINEL_ACT),跨多次进入复用;run_now_playing() 进入 push
|
||||
* 哨兵、退出 pop(owner 闸门使控件命中生效)。
|
||||
* ================================================================== */
|
||||
#define NP_SENTINEL_ACT 0x51 /* Now Playing 哨兵 activity */
|
||||
|
||||
static meow_widget *g_np_prog = NULL;
|
||||
static meow_widget *g_np_prev = NULL, *g_np_play = NULL, *g_np_pause = NULL, *g_np_next = NULL;
|
||||
static int g_np_init = 0;
|
||||
|
||||
static void np_widgets_create(void)
|
||||
{
|
||||
meow_ui_activity_push(NP_SENTINEL_ACT);
|
||||
g_np_prog = meow_progress_create(NP_PROG_X, NP_PROG_Y, NP_PROG_W, 6, 0);
|
||||
g_np_prev = meow_iconbtn_create(NP_PREV_CX - NP_PREV_R, NP_BTN_Y - NP_PREV_R,
|
||||
NP_PREV_R * 2, MEOW_ICON_SKIP_PREV);
|
||||
g_np_play = meow_iconbtn_create(NP_PLAY_CX - NP_PLAY_R, NP_BTN_Y - NP_PLAY_R,
|
||||
NP_PLAY_R * 2, MEOW_ICON_PLAY_ARROW);
|
||||
g_np_pause = meow_iconbtn_create(NP_PLAY_CX - NP_PLAY_R, NP_BTN_Y - NP_PLAY_R,
|
||||
NP_PLAY_R * 2, MEOW_ICON_PAUSE);
|
||||
g_np_next = meow_iconbtn_create(NP_NEXT_CX - NP_PREV_R, NP_BTN_Y - NP_PREV_R,
|
||||
NP_PREV_R * 2, MEOW_ICON_SKIP_NEXT);
|
||||
/* 主播放钮保持「强调动作」观感:底色=primary、图标=onPrimary;其余两钮默认 surfaceContainerLow。 */
|
||||
const meow_theme *th = meow_theme_get();
|
||||
meow_widget_opts op; memset(&op, 0, sizeof op);
|
||||
op.bg = th->primary; op.fg = th->onPrimary;
|
||||
if (g_np_play) meow_widget_set_opts(g_np_play, &op);
|
||||
if (g_np_pause) meow_widget_set_opts(g_np_pause, &op);
|
||||
meow_ui_activity_pop();
|
||||
g_np_init = 1;
|
||||
}
|
||||
|
||||
/* 主题刷新:播放钮底色/图标随当前主题(明暗/风格切换后跟手)。 */
|
||||
static void np_refresh_theme(void)
|
||||
{
|
||||
if (!g_np_init) return;
|
||||
const meow_theme *th = meow_theme_get();
|
||||
meow_widget_opts op; memset(&op, 0, sizeof op);
|
||||
op.bg = th->primary; op.fg = th->onPrimary;
|
||||
if (g_np_play) meow_widget_set_opts(g_np_play, &op);
|
||||
if (g_np_pause) meow_widget_set_opts(g_np_pause, &op);
|
||||
}
|
||||
|
||||
/* 绘制播放控制三钮(prev/next 固定;play/pause 按会话状态只画其一——两钮同位,改画时
|
||||
* 上一帧残留被新画圆底盖掉)。 */
|
||||
static void np_draw_ctl(const meow_media_session_t *s)
|
||||
{
|
||||
np_refresh_theme();
|
||||
if (g_np_prev) { meow_widget_set_selected(g_np_prev, 0); meow_widget_draw(g_np_prev); }
|
||||
if (g_np_next) { meow_widget_set_selected(g_np_next, 0); meow_widget_draw(g_np_next); }
|
||||
int playing = (s && s->state == MEOW_MEDIA_PLAYING);
|
||||
meow_widget *pb = playing ? g_np_pause : g_np_play;
|
||||
if (pb) { meow_widget_set_selected(pb, 0); meow_widget_draw(pb); }
|
||||
}
|
||||
|
||||
/* 进度带(进度条 + 时间)绘制;pos = 当前显示位置。进度条走 SDK meow_progress。 */
|
||||
static void np_draw_progress(const meow_media_session_t *s, uint32_t pos, const meow_ui_theme_t *th)
|
||||
{
|
||||
fill_rect(NP_PROG_X, NP_PROG_Y, NP_PROG_W, 6, th->outline);
|
||||
int fw = (s->dur_ms > 0) ? (int)((uint64_t)pos * NP_PROG_W / s->dur_ms) : 0;
|
||||
if (fw > NP_PROG_W) fw = NP_PROG_W;
|
||||
if (fw > 0) fill_rect(NP_PROG_X, NP_PROG_Y, fw, 6, th->primary);
|
||||
int pct = (s->dur_ms > 0) ? (int)((uint64_t)pos * 100 / s->dur_ms) : 0;
|
||||
if (pct > 100) pct = 100;
|
||||
if (g_np_prog) { meow_progress_set(g_np_prog, pct); meow_widget_draw(g_np_prog); }
|
||||
/* 时间(左=当前,右=总长;MM:SS) */
|
||||
char l[16], rbuf[16];
|
||||
unsigned lm = pos / 60000u, ls = (pos % 60000u) / 1000u;
|
||||
@@ -120,16 +185,17 @@ static void np_draw_page(int redraw_sb)
|
||||
{
|
||||
const meow_ui_theme_t *th = s_ui_theme();
|
||||
int W = fb_xres, H = fb_yres;
|
||||
if (!g_np_init) np_widgets_create(); /* M7.0b:lazy 建控件(跨进入复用) */
|
||||
if (redraw_sb) fill_rect(0, 0, W, SB_BAR_H, th->surface);
|
||||
fill_rect(0, SB_BAR_H, W, H - SB_BAR_H, th->surface);
|
||||
const meow_media_session_t *s = meow_media_current();
|
||||
if (!s || s->state == MEOW_MEDIA_STOPPED) {
|
||||
/* 空态占位 */
|
||||
const char *t1 = "未在播放";
|
||||
/* 空态占位(M7.0b 文案走 meow_str,未知 id 回退中文) */
|
||||
const char *t1 = meow_str_zh("np.not_playing", "未在播放");
|
||||
ui_draw((W - ui_width(t1, 26)) / 2, 300, t1, th->on_surface_variant, 26);
|
||||
const char *t2 = "打开播放 App 以显示正在播放";
|
||||
const char *t2 = meow_str_zh("np.open_app_hint", "打开播放 App 以显示正在播放");
|
||||
ui_draw((W - ui_width(t2, 18)) / 2, 348, t2, th->on_surface_variant, 18);
|
||||
const char *t3 = "左缘右滑返回";
|
||||
const char *t3 = meow_str_zh("np.edge_back", "左缘右滑返回");
|
||||
ui_draw((W - ui_width(t3, 16)) / 2, 396, t3, th->on_surface_variant, 16);
|
||||
if (redraw_sb) draw_statusbar();
|
||||
return;
|
||||
@@ -152,16 +218,13 @@ static void np_draw_page(int redraw_sb)
|
||||
np_center_text(NP_ARTIST_Y, s->artist, 18, th->on_surface_variant, W - 60);
|
||||
if (s->album[0])
|
||||
np_center_text(NP_ALBUM_Y, s->album, 16, th->on_surface_variant, W - 80);
|
||||
/* 进度 */
|
||||
/* 进度(SDK meow_progress) */
|
||||
uint32_t pos = meow_media_display_pos(s);
|
||||
np_draw_progress(s, pos, th);
|
||||
/* 控制按钮 */
|
||||
np_btn(NP_PREV_CX, NP_BTN_Y, NP_PREV_R, 0, th);
|
||||
int pk = (s->state == MEOW_MEDIA_PLAYING) ? 3 : 1;
|
||||
np_btn(NP_PLAY_CX, NP_BTN_Y, NP_PLAY_R, pk, th);
|
||||
np_btn(NP_NEXT_CX, NP_BTN_Y, NP_PREV_R, 2, th);
|
||||
/* 歌词占位 */
|
||||
const char *ly = "歌词(占位)";
|
||||
/* 控制按钮(SDK meow_iconbtn,命中/状态走 SDK) */
|
||||
np_draw_ctl(s);
|
||||
/* 歌词占位(M7.0b 文案走 meow_str) */
|
||||
const char *ly = meow_str_zh("np.lyric_placeholder", "歌词(占位)");
|
||||
ui_draw((W - ui_width(ly, 16)) / 2, NP_LYRIC_Y, ly, th->on_surface_variant, 16);
|
||||
if (redraw_sb) draw_statusbar();
|
||||
}
|
||||
@@ -176,25 +239,20 @@ static void np_repaint_progress(void)
|
||||
/* 清进度带 + 控制带,再重绘(只脏这两带,不整屏)。 */
|
||||
fill_rect(0, NP_TIME_Y, fb_xres, NP_BTN_Y + NP_PLAY_R - NP_TIME_Y, th->surface);
|
||||
np_draw_progress(s, pos, th);
|
||||
np_btn(NP_PREV_CX, NP_BTN_Y, NP_PREV_R, 0, th);
|
||||
np_btn(NP_PLAY_CX, NP_BTN_Y, NP_PLAY_R, (s->state == MEOW_MEDIA_PLAYING) ? 3 : 1, th);
|
||||
np_btn(NP_NEXT_CX, NP_BTN_Y, NP_PREV_R, 2, th);
|
||||
np_draw_ctl(s);
|
||||
meow_dirty_add(0, NP_TIME_Y, fb_xres, NP_BTN_Y + NP_PLAY_R - NP_TIME_Y);
|
||||
meow_ui_flush();
|
||||
}
|
||||
|
||||
/* 控制按钮命中:返回 cmd(1-4),0=未命中。 */
|
||||
/* 控制按钮命中:返回 cmd(1-4),0=未命中。走 SDK 圆形命中(owner==哨兵 + enabled 闸门)。
|
||||
* 播放/暂停两钮同位:命中任一(同矩形)→ 按会话状态分派 play(1)/pause(2)。 */
|
||||
static int np_btn_tap(int tx, int ty)
|
||||
{
|
||||
if (tx >= NP_PREV_CX - NP_PREV_R && tx <= NP_PREV_CX + NP_PREV_R &&
|
||||
ty >= NP_BTN_Y - NP_PREV_R && ty <= NP_BTN_Y + NP_PREV_R) return 3;
|
||||
if (tx >= NP_PLAY_CX - NP_PLAY_R && tx <= NP_PLAY_CX + NP_PLAY_R &&
|
||||
ty >= NP_BTN_Y - NP_PLAY_R && ty <= NP_BTN_Y + NP_PLAY_R) {
|
||||
const meow_media_session_t *s = meow_media_current();
|
||||
const meow_media_session_t *s = meow_media_current();
|
||||
if (g_np_prev && meow_widget_hit(g_np_prev, tx, ty)) return 3;
|
||||
if (g_np_play && meow_widget_hit(g_np_play, tx, ty))
|
||||
return (s && s->state == MEOW_MEDIA_PLAYING) ? 2 : 1;
|
||||
}
|
||||
if (tx >= NP_NEXT_CX - NP_PREV_R && tx <= NP_NEXT_CX + NP_PREV_R &&
|
||||
ty >= NP_BTN_Y - NP_PREV_R && ty <= NP_BTN_Y + NP_PREV_R) return 4;
|
||||
if (g_np_next && meow_widget_hit(g_np_next, tx, ty)) return 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -351,6 +409,7 @@ void run_now_playing(void)
|
||||
}
|
||||
usleep(10000);
|
||||
}
|
||||
meow_ui_activity_pop(); /* M7.0b:退出 Now Playing,回主 activity(控件 owner 仍钉哨兵,复用) */
|
||||
if (tfd >= 0) close(tfd);
|
||||
kp_close(&kp_keys);
|
||||
kp_close(&kp_power);
|
||||
|
||||
Reference in new issue
Block a user