From 27ce660c5cdfce887710df772d372e9c5b910753 Mon Sep 17 00:00:00 2001 From: Josiah Date: Mon, 31 Aug 2026 12:03:32 -0400 Subject: [PATCH] fw/quick_launch: add a Nothing action for inert buttons The "disable" Quick Launch action previously would open the Quick Launch settings menu, which means there was no actual option to "do nothing." Renamed the current "Disable" option to "Unassigned", and added a new "Nothing" action that actually does nothing. "Unassigned" is still the default. Fixes coredevices/PebbleOS#1763 Signed-off-by: Josiah Bloomer Co-Authored-By: Claude Opus 5 --- src/fw/apps/system/quick_launch_nothing.c | 26 +++++++++++++++++++ src/fw/apps/system/quick_launch_nothing.h | 11 ++++++++ src/fw/apps/system/settings/quick_launch.c | 4 +-- .../system/settings/quick_launch_app_menu.c | 3 ++- .../normal/system_app_registry_list.json | 5 ++++ src/fw/shell/normal/watchface.c | 4 +++ 6 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/fw/apps/system/quick_launch_nothing.c create mode 100644 src/fw/apps/system/quick_launch_nothing.h diff --git a/src/fw/apps/system/quick_launch_nothing.c b/src/fw/apps/system/quick_launch_nothing.c new file mode 100644 index 0000000000..c63dca294c --- /dev/null +++ b/src/fw/apps/system/quick_launch_nothing.c @@ -0,0 +1,26 @@ +/* SPDX-FileCopyrightText: 2026 Core Devices LLC */ +/* SPDX-License-Identifier: Apache-2.0 */ + +//! The "Nothing" Quick Launch action. Binding a button to it makes the button +//! inert: the shell recognizes the app id and never launches anything. + +#include "quick_launch_nothing.h" + +#include "pbl/services/i18n/i18n.h" + +static void prv_main(void) { + // Never runs; the shell drops the launch before it gets here. +} + +const PebbleProcessMd *quick_launch_nothing_get_app_info(void) { + static const PebbleProcessMdSystem s_app_info = { + .common = { + .main_func = &prv_main, + .uuid = QUICK_LAUNCH_NOTHING_UUID, + .visibility = ProcessVisibilityQuickLaunch, + }, + /// Quick Launch action that makes the button do nothing at all. + .name = i18n_noop("Nothing"), + }; + return &s_app_info.common; +} diff --git a/src/fw/apps/system/quick_launch_nothing.h b/src/fw/apps/system/quick_launch_nothing.h new file mode 100644 index 0000000000..b8628a952e --- /dev/null +++ b/src/fw/apps/system/quick_launch_nothing.h @@ -0,0 +1,11 @@ +/* SPDX-FileCopyrightText: 2026 Core Devices LLC */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#pragma once + +#include "process_management/app_manager.h" + +#define QUICK_LAUNCH_NOTHING_UUID {0xde, 0x6d, 0xa1, 0x7f, 0x1a, 0x10, 0x47, 0x25, \ + 0xad, 0xbb, 0x1e, 0xfc, 0x22, 0xe4, 0x3f, 0x04} + +const PebbleProcessMd *quick_launch_nothing_get_app_info(void); diff --git a/src/fw/apps/system/settings/quick_launch.c b/src/fw/apps/system/settings/quick_launch.c index aa1d1f5d33..fdfd9f8f12 100644 --- a/src/fw/apps/system/settings/quick_launch.c +++ b/src/fw/apps/system/settings/quick_launch.c @@ -59,8 +59,8 @@ static const char *s_row_titles[NUM_ROWS] = { static void prv_get_subtitle_string(AppInstallId app_id, QuickLaunchData *data, char *buffer, uint8_t buf_len) { if (app_id == INSTALL_ID_INVALID) { - /// Shown in Quick Launch Settings when the button is disabled. - i18n_get_with_buffer("Disabled", buffer, buf_len); + /// Shown in Quick Launch Settings when no action or app is bound to the button. + i18n_get_with_buffer("Unassigned", buffer, buf_len); return; } else { AppInstallEntry entry; diff --git a/src/fw/apps/system/settings/quick_launch_app_menu.c b/src/fw/apps/system/settings/quick_launch_app_menu.c index b1980007a8..4d1311638e 100644 --- a/src/fw/apps/system/settings/quick_launch_app_menu.c +++ b/src/fw/apps/system/settings/quick_launch_app_menu.c @@ -86,7 +86,8 @@ static void prv_menu_draw_row(OptionMenu *option_menu, GContext* ctx, const Laye QuickLaunchAppMenuData *data = context; const char *text = NULL; if (row == 0) { - text = i18n_get("Disable", data); + /// Shown in Quick Launch Settings when no action or app is bound to the button. + text = i18n_get("Unassigned", data); } else { AppMenuNode *node = app_menu_data_source_get_node_at_index(&data->data_source, row - NUM_CUSTOM_CELLS); diff --git a/src/fw/shell/normal/system_app_registry_list.json b/src/fw/shell/normal/system_app_registry_list.json index 773c08ee50..8dd4bb68e2 100644 --- a/src/fw/shell/normal/system_app_registry_list.json +++ b/src/fw/shell/normal/system_app_registry_list.json @@ -673,6 +673,11 @@ "id": -100, "enum": "NOTIFICATIONS_CLEAR_HISTORY", "md_fn": "notifications_clear_history_app_get_info" + }, + { + "id": -101, + "enum": "QUICK_LAUNCH_NOTHING", + "md_fn": "quick_launch_nothing_get_app_info" } ], "resource_apps": [ diff --git a/src/fw/shell/normal/watchface.c b/src/fw/shell/normal/watchface.c index 0afacd03f2..45ff0ef3f7 100644 --- a/src/fw/shell/normal/watchface.c +++ b/src/fw/shell/normal/watchface.c @@ -187,6 +187,10 @@ static void prv_launch_timeline_app(AppInstallId app_id, ButtonId button, static void prv_launch_quick_launch_app(AppInstallId app_id, ButtonId button, AppLaunchReason timeline_reason, AppQuickLaunchAction action) { + if (app_id == APP_ID_QUICK_LAUNCH_NOTHING) { + return; + } + const bool is_timeline = (app_id == APP_ID_TIMELINE) || (app_id == APP_ID_TIMELINE_PAST) || (app_id == APP_ID_TIMELINE_FULL);