feat(launcher): 蓝牙/WiFi 独立子页面(安卓风)— 新增 subpage.c 统一脚手架(顶栏+分组列表+跟手滚动+左缘返回) + wifi_page.c(开关/当前连接详情/已保存/附近,BSSID去重+中文SSID) + bt_page.c(开关/已连接/已配对/附近扫描配对);SMENU 网络组收敛为 2 入口行 (agent-178)

launcher bd37c8b0→d10c0e8a; 改动文件 -Wall -Wextra 0 warning; 真机待验证: 蓝牙 pair/connect、开关联动、触摸几何
出入: 中文SSID/BSSID去重复用 net.c 既有实现; 模态复用 s_dd_modal(SDK 模态层未上收, 未改 SDK); s_net_open 旧分支留作死代码未删
This commit is contained in:
MeowOS committed 2026-08-31 03:41:51 +08:00
1 parent 366bf6bb5d
commit f2786552d5
10 files changed
+1122 -86

No files matched your search

+64 -63
View File
@@ -43,79 +43,76 @@ static const int s_time_tiers[] = {
/* 分组/键/类型/默认与 SYSTEM_SETTINGS.md §1 一致(新建项四端同步)。 */
static const srow_t SMENU[] = {
/* 显示 */
{ "显示", NULL, SC_HEADER, 0,0,0, NULL,NULL,0 },
{ "亮度", "display.brightness", SC_SLIDER, 1,100,1, NULL,NULL,0 },
{ "息屏模式", "display.screen_off_mode", SC_ENUM, 0,0,0, NULL,NULL,0 },
{ "息屏时间", "display.screen_off_timeout", SC_SLIDER, 0,(S_TIME_TIERS_N-1),1, NULL,NULL,0 },
{ "刷新率", "display.refresh_rate", SC_ENUM, 0,0,0, NULL,NULL,0 },
{ "最高刷新率", "display.refresh_always_max", SC_SWITCH, 0,0,0, NULL,NULL,0 },
{ "显示", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
{ "亮度", "display.brightness", SC_SLIDER, 1,100,1, NULL,NULL,0,0 },
{ "息屏模式", "display.screen_off_mode", SC_ENUM, 0,0,0, NULL,NULL,0,0 },
{ "息屏时间", "display.screen_off_timeout", SC_SLIDER, 0,(S_TIME_TIERS_N-1),1, NULL,NULL,0,0 },
{ "刷新率", "display.refresh_rate", SC_ENUM, 0,0,0, NULL,NULL,0,0 },
{ "最高刷新率", "display.refresh_always_max", SC_SWITCH, 0,0,0, NULL,NULL,0,0 },
/* B2b 主题三方式:标题行「主题」改选 display.theme_mode(手动/时段自动),
* 手动深浅由下方「主题深浅」(display.theme) 控制;时段两键为分钟滑条(STEP=15)。 */
{ "主题", "display.theme_mode", SC_ENUM, 0,0,0, NULL,NULL,0 },
{ "主题深浅", "display.theme", SC_ENUM, 0,0,0, NULL,NULL,0 },
{ "深色时段开始", "display.theme_dark_start", SC_SLIDER, 0,1439,15, NULL,NULL,0 },
{ "深色时段结束", "display.theme_dark_end", SC_SLIDER, 0,1439,15, NULL,NULL,0 },
{ "背景", "display.background", SC_PRESET, 0,0,0, bg_presets, bg_preset_labels, BG_PRESETS_N },
/* 网络 */
{ "网络", NULL, SC_HEADER, 0,0,0, NULL,NULL,0 },
{ "WiFi", "network.wifi_enabled", SC_SWITCH, 0,0,0, NULL,NULL,0 },
{ "WiFi连接", NULL, SC_LIST, 0,0,0, NULL,NULL,0, NET_LIST_WIFI_SSID },
{ "已保存网络", NULL, SC_LIST, 0,0,0, NULL,NULL,0, NET_LIST_WIFI_SAVED },
{ "附近WiFi", NULL, SC_LIST, 0,0,0, NULL,NULL,0, NET_LIST_WIFI_SCAN },
{ "蓝牙", "network.bluetooth_enabled", SC_SWITCH, 0,0,0, NULL,NULL,0 },
{ "蓝牙模式", NULL, SC_INFO, 0,0,0, NULL,NULL,0, NET_LIST_BT_MODE },
{ "蓝牙设备", NULL, SC_LIST, 0,0,0, NULL,NULL,0, NET_LIST_BT_NEARBY },
{ "主题", "display.theme_mode", SC_ENUM, 0,0,0, NULL,NULL,0,0 },
{ "主题深浅", "display.theme", SC_ENUM, 0,0,0, NULL,NULL,0,0 },
{ "深色时段开始", "display.theme_dark_start", SC_SLIDER, 0,1439,15, NULL,NULL,0,0 },
{ "深色时段结束", "display.theme_dark_end", SC_SLIDER, 0,1439,15, NULL,NULL,0,0 },
{ "背景", "display.background", SC_PRESET, 0,0,0, bg_presets, bg_preset_labels, BG_PRESETS_N,0 },
/* 网络:M2.76 WiFi/蓝牙升级为独立子页面(安卓风)。入口行为「列表行」+右侧 chevron,
* 摘要显示当前状态(s_net_get);点开进入对应子页(顶栏+返回+分组列表),详见
* wifi_page.c / bt_page.c。原来散落的开关/列表/信息行收敛进子页面。 */
{ "网络", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
{ "WiFi", NULL, SC_LIST, 0,0,0, NULL,NULL,0, NET_LIST_WIFI_PAGE },
{ "蓝牙", NULL, SC_LIST, 0,0,0, NULL,NULL,0, NET_LIST_BT_PAGE },
/* 电源 */
{ "电源", NULL, SC_HEADER, 0,0,0, NULL,NULL,0 },
{ "长按弹菜单", "power.longpress_menu_ms", SC_SLIDER, 500,5000,500, NULL,NULL,0 },
{ "长按强关", "power.forceoff_ms", SC_SLIDER, 5500,15000,500, NULL,NULL,0 },
{ "退出热键", "power.defeat_hotkey", SC_PRESET, 0,0,0, hk_presets, hk_preset_labels, HK_PRESETS_N },
{ "电源", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
{ "长按弹菜单", "power.longpress_menu_ms", SC_SLIDER, 500,5000,500, NULL,NULL,0,0 },
{ "长按强关", "power.forceoff_ms", SC_SLIDER, 5500,15000,500, NULL,NULL,0,0 },
{ "退出热键", "power.defeat_hotkey", SC_PRESET, 0,0,0, hk_presets, hk_preset_labels, HK_PRESETS_N,0 },
/* 开机 */
{ "开机", NULL, SC_HEADER, 0,0,0, NULL,NULL,0 },
{ "默认系统", "boot.default", SC_ENUM, 0,0,0, NULL,NULL,0 },
{ "显示选单", "boot.menu_enabled", SC_SWITCH, 0,0,0, NULL,NULL,0 },
{ "选单超时", "boot.timeout_ms", SC_SLIDER, 0,30000,500, NULL,NULL,0 },
{ "开机", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
{ "默认系统", "boot.default", SC_ENUM, 0,0,0, NULL,NULL,0,0 },
{ "显示选单", "boot.menu_enabled", SC_SWITCH, 0,0,0, NULL,NULL,0,0 },
{ "选单超时", "boot.timeout_ms", SC_SLIDER, 0,30000,500, NULL,NULL,0,0 },
/* 输入 */
{ "输入", NULL, SC_HEADER, 0,0,0, NULL,NULL,0 },
{ "热键序列", "input.hotkey_seq", SC_PRESET, 0,0,0, seq_presets, seq_preset_labels, SEQ_PRESETS_N },
{ "热键窗口", "input.hotkey_window_ms", SC_SLIDER, 0,5000,100, NULL,NULL,0 },
{ "触摸布防", "input.touch_arm_delay_ms", SC_SLIDER, 0,2000,50, NULL,NULL,0 },
{ "滑动方向", "input.swipe_invert", SC_SWITCH, 0,0,0, NULL,NULL,0 },
{ "输入", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
{ "热键序列", "input.hotkey_seq", SC_PRESET, 0,0,0, seq_presets, seq_preset_labels, SEQ_PRESETS_N,0 },
{ "热键窗口", "input.hotkey_window_ms", SC_SLIDER, 0,5000,100, NULL,NULL,0,0 },
{ "触摸布防", "input.touch_arm_delay_ms", SC_SLIDER, 0,2000,50, NULL,NULL,0,0 },
{ "滑动方向", "input.swipe_invert", SC_SWITCH, 0,0,0, NULL,NULL,0,0 },
/* 字体主题 */
{ "字体主题", NULL, SC_HEADER, 0,0,0, NULL,NULL,0 },
{ "字体文件", "font.file", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0 },
{ "字体主题", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
{ "字体文件", "font.file", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0,0 },
/* M2.5x 字体档位分层/按需大字库:「加载大字库」= font.load_full(int 0/1 默认 0)。
* 开 → 强制全系统用大字库 gbk≈20k 档(覆盖 app 未声明/覆盖默认 font.file);
* 关(默认)→ 小字库 common≈4k,仅 app 声明 fonts:"full" 才大字库。 */
{ "加载大字库", "font.load_full", SC_SWITCH, 0,0,0, NULL,NULL,0 },
{ "加载大字库", "font.load_full", SC_SWITCH, 0,0,0, NULL,NULL,0,0 },
/* M2.5x 多字体:开关 + 6 个字符类别字体(preset=可用 MeowOS/fonts/<family>/<weight>/ 列表;
* 值空 = 跟随全局 font.file)。仅开关开启时 6 行可见(s_row_visible)。 */
{ "多字体", "display.multi_font", SC_SWITCH, 0,0,0, NULL,NULL,0 },
{ "中文(CJK)", "font.class_cjk", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0 },
{ "中文标点", "font.class_cjk_sym", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0 },
{ "数字", "font.class_num", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0 },
{ "拉丁字母", "font.class_latin", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0 },
{ "半角标点", "font.class_latin_sym", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0 },
{ "其他字符", "font.class_other", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0 },
{ "标题字号", "font.size.title", SC_SLIDER, 16,40,1, NULL,NULL,0 },
{ "正文字号", "font.size.body", SC_SLIDER, 12,28,1, NULL,NULL,0 },
{ "UI风格", "ui.style", SC_ENUM, 0,0,0, NULL,NULL,0 },
{ "多字体", "display.multi_font", SC_SWITCH, 0,0,0, NULL,NULL,0,0 },
{ "中文(CJK)", "font.class_cjk", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0,0 },
{ "中文标点", "font.class_cjk_sym", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0,0 },
{ "数字", "font.class_num", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0,0 },
{ "拉丁字母", "font.class_latin", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0,0 },
{ "半角标点", "font.class_latin_sym", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0,0 },
{ "其他字符", "font.class_other", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0,0 },
{ "标题字号", "font.size.title", SC_SLIDER, 16,40,1, NULL,NULL,0,0 },
{ "正文字号", "font.size.body", SC_SLIDER, 12,28,1, NULL,NULL,0,0 },
{ "UI风格", "ui.style", SC_ENUM, 0,0,0, NULL,NULL,0,0 },
/* 通知 */
{ "通知", NULL, SC_HEADER, 0,0,0, NULL,NULL,0 },
{ "通知中心", "notify.center_enabled", SC_SWITCH, 0,0,0, NULL,NULL,0 },
{ "应用配额", "notify.app_quota", SC_SLIDER, 1,64,1, NULL,NULL,0 },
{ "通知", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
{ "通知中心", "notify.center_enabled", SC_SWITCH, 0,0,0, NULL,NULL,0,0 },
{ "应用配额", "notify.app_quota", SC_SLIDER, 1,64,1, NULL,NULL,0,0 },
/* 日志 */
{ "日志", NULL, SC_HEADER, 0,0,0, NULL,NULL,0 },
{ "日志级别", "log.level", SC_ENUM, 0,0,0, NULL,NULL,0 },
{ "写入TF卡", "log.to_card", SC_SWITCH, 0,0,0, NULL,NULL,0 },
{ "日志", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
{ "日志级别", "log.level", SC_ENUM, 0,0,0, NULL,NULL,0,0 },
{ "写入TF卡", "log.to_card", SC_SWITCH, 0,0,0, NULL,NULL,0,0 },
/* 音频 */
{ "音频", NULL, SC_HEADER, 0,0,0, NULL,NULL,0 },
{ "音量", "audio.volume", SC_SLIDER, 0,100,1, NULL,NULL,0 },
{ "音量上限", "audio.volume_max", SC_SLIDER, 0,100,1, NULL,NULL,0 },
{ "音量跳步", "audio.volume_step", SC_SLIDER, 1,5,1, NULL,NULL,0 },
{ "输出设备", "audio.output", SC_PRESET, 0,0,0, out_presets, out_preset_labels, OUT_PRESETS_N },
{ "音频", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
{ "音量", "audio.volume", SC_SLIDER, 0,100,1, NULL,NULL,0,0 },
{ "音量上限", "audio.volume_max", SC_SLIDER, 0,100,1, NULL,NULL,0,0 },
{ "音量跳步", "audio.volume_step", SC_SLIDER, 1,5,1, NULL,NULL,0,0 },
{ "输出设备", "audio.output", SC_PRESET, 0,0,0, out_presets, out_preset_labels, OUT_PRESETS_N,0 },
/* 关于(设置列表最底;「关于本机」点开 s_about_open 弹只读设备信息框) */
{ "关于", NULL, SC_HEADER, 0,0,0, NULL,NULL,0 },
{ "关于", NULL, SC_HEADER, 0,0,0, NULL,NULL,0,0 },
{ "关于本机", NULL, SC_LIST, 0,0,0, NULL,NULL,0, NET_LIST_ABOUT },
};
@@ -1043,11 +1040,11 @@ void run_settings_page(void)
if (pwr && pwr_hold_at) {
/* M2.10/M2.11 B/M2.37 同款:8s 强关只在该「按住」从未开过菜单(!pwr_menu_state)
* 时触发;开过菜单则交给菜单内确认/取消,杜绝「开菜单->取消->仍按住->强关」残留。 */
if (now - pwr_hold_at >= power_forceoff_ms && !pwr_menu_state) {
if (now - pwr_hold_at >= (unsigned long long)power_forceoff_ms && !pwr_menu_state) {
if (sim_no_exec) { logmsg("settings pm: [sim-no-exec] POWER HOLD %dms -> would force poweroff", power_forceoff_ms); }
else { logmsg("settings pm: POWER HOLD %dms -> force poweroff", power_forceoff_ms); meow_power_action(POWER_SHUTDOWN); }
/* 关机一般不复返;若 reboot 失败返回仍按按住处理(m_prev 由下方统一复写) */
} else if (now - pwr_hold_at >= power_longpress_menu_ms && !pwr_menu_state) {
} else if (now - pwr_hold_at >= (unsigned long long)power_longpress_menu_ms && !pwr_menu_state) {
pwr_menu_state = 1;
logmsg("settings pm: POWER HOLD %dms -> show power menu", power_longpress_menu_ms);
show_power_menu(); /* 动作在函数内 system();取消则续循环 */
@@ -1076,7 +1073,7 @@ void run_settings_page(void)
/* 松开:短按(<长按阈值且菜单未开)→ 单击 = 息屏/亮屏切换 */
if (pwr_suppress_click) {
logmsg("settings pm: power release after power-menu -> no toggle (suppress)");
} else if (pwr_hold_at && (now - pwr_hold_at < power_longpress_menu_ms) && !pwr_menu_state && !pwr_woke) {
} else if (pwr_hold_at && (now - pwr_hold_at < (unsigned long long)power_longpress_menu_ms) && !pwr_menu_state && !pwr_woke) {
logmsg("settings pm: power single-click -> toggle panel (was %s)", meow_screen_on ? "on" : "off");
meow_toggle_panel();
meow_auto_slept = 0; /* M2.17:手动/自动息屏后电源单击唤醒均清自动态 */
@@ -1200,9 +1197,13 @@ void run_settings_page(void)
s_commit(r, 1);
} else if (r->ctrl == SC_LIST) {
/* M2.39 网络列表行:开下拉(重新解析)+ 重绘 + 排空本页 tfd
* (复刻 s_dropdown 后的穿透防护,见下方 ENUM/PRESET 分支)。 */
* (复刻 s_dropdown 后的穿透防护,见下方 ENUM/PRESET 分支)。
* M2.76:WiFi/蓝牙升级为独立子页面 → 点开进 run_wifi_page/
* run_bt_page(阻塞,内部自开 fds;返回后仍须排空本页 tfd)。 */
after_modal = 1;
s_net_open(r);
if (r->net_list == NET_LIST_WIFI_PAGE) { run_wifi_page(); s_net_refresh(); }
else if (r->net_list == NET_LIST_BT_PAGE) { run_bt_page(); s_net_refresh(); }
else s_net_open(r);
if (tfd >= 0) {
unsigned char e[16];
while (read(tfd, e, sizeof e) == 16) {}