ui: add custom button navigation actions

This commit is contained in:
royjr
2026-08-16 16:24:42 -04:00
parent 9af59caf9c
commit bf0cdd667b
7 changed files with 76 additions and 22 deletions
+1 -1
View File
@@ -186,7 +186,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"ShowTurnSignals", {PERSISTENT | BACKUP, BOOL, "0"}},
{"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}},
{"TrueVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
{"SteeringCustomButtonMapping", {PERSISTENT | BACKUP, INT, "0"}},
{"CustomButtonAction", {PERSISTENT | BACKUP, INT, "0"}},
// MADS params
{"Mads", {PERSISTENT | BACKUP, BOOL, "1"}},
+21 -2
View File
@@ -3,7 +3,7 @@ from enum import IntEnum
import openpilot.cereal.messaging as messaging
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.widgets import Widget
from openpilot.selfdrive.ui.sunnypilot.custom_button import handle_custom_button
from openpilot.selfdrive.ui.sunnypilot.custom_button import CustomButtonAction, handle_custom_button
from openpilot.selfdrive.ui.layouts.sidebar import Sidebar, SIDEBAR_WIDTH
from openpilot.selfdrive.ui.layouts.home import HomeLayout
from openpilot.selfdrive.ui.layouts.settings.settings import SettingsLayout, PanelType
@@ -41,6 +41,13 @@ class MainLayout(Widget):
MainState.SETTINGS: SettingsLayout(),
MainState.ONROAD: AugmentedRoadView(),
}
self._custom_button_callbacks = {
CustomButtonAction.BOOKMARK: self._on_bookmark_clicked,
CustomButtonAction.QUIET_MODE: self._toggle_quiet_mode,
CustomButtonAction.ONROAD: self._show_onroad,
CustomButtonAction.HOME: self._show_home,
CustomButtonAction.SETTINGS: self._on_settings_clicked,
}
self._sidebar_rect = rl.Rectangle(0, 0, 0, 0)
self._content_rect = rl.Rectangle(0, 0, 0, 0)
@@ -56,7 +63,7 @@ class MainLayout(Widget):
gui_app.push_widget(self._onboarding_window)
def _render(self, _):
handle_custom_button(ui_state.sm, ui_state.params, self._on_bookmark_clicked)
handle_custom_button(ui_state.sm, ui_state.params, self._custom_button_callbacks)
self._handle_onroad_transition()
self._render_main_content()
@@ -116,6 +123,18 @@ class MainLayout(Widget):
def _on_settings_clicked(self):
self.open_settings(PanelType.DEVICE)
@staticmethod
def _toggle_quiet_mode():
ui_state.params.put_bool('QuietMode', not ui_state.params.get_bool('QuietMode'))
def _show_onroad(self):
self._set_current_layout(MainState.ONROAD)
self._sidebar.set_visible(False)
def _show_home(self):
self._set_current_layout(MainState.HOME)
self._sidebar.set_visible(True)
def _on_bookmark_clicked(self):
for service in ('bookmarkButton', 'userBookmark'):
msg = messaging.new_message(service, valid=True)
+22 -2
View File
@@ -4,7 +4,7 @@ from openpilot.selfdrive.ui.mici.layouts.home import MiciHomeLayout
from openpilot.selfdrive.ui.mici.layouts.settings.settings import SettingsLayout
from openpilot.selfdrive.ui.mici.layouts.offroad_alerts import MiciOffroadAlerts
from openpilot.selfdrive.ui.mici.onroad.augmented_road_view import AugmentedRoadView
from openpilot.selfdrive.ui.sunnypilot.custom_button import handle_custom_button
from openpilot.selfdrive.ui.sunnypilot.custom_button import CustomButtonAction, handle_custom_button
from openpilot.selfdrive.ui.ui_state import device, ui_state
from openpilot.selfdrive.ui.mici.layouts.onboarding import OnboardingWindow
from openpilot.selfdrive.ui.body.layouts.onroad import BodyLayout
@@ -36,6 +36,13 @@ class MiciMainLayout(Scroller):
self._settings_layout = SettingsLayout()
self._car_onroad_layout = AugmentedRoadView(bookmark_callback=self._on_bookmark_clicked)
self._body_onroad_layout = BodyLayout()
self._custom_button_callbacks = {
CustomButtonAction.BOOKMARK: self._on_bookmark_clicked,
CustomButtonAction.QUIET_MODE: self._toggle_quiet_mode,
CustomButtonAction.ONROAD: lambda: self._show_layout(self._onroad_layout),
CustomButtonAction.HOME: lambda: self._show_layout(self._home_layout),
CustomButtonAction.SETTINGS: self._show_settings,
}
# Initialize widget rects
for widget in (self._home_layout, self._alerts_layout, self._settings_layout,
@@ -96,7 +103,7 @@ class MiciMainLayout(Scroller):
self._alerts_layout._update_state()
def _render(self, _):
handle_custom_button(ui_state.sm, ui_state.params, self._on_bookmark_clicked)
handle_custom_button(ui_state.sm, ui_state.params, self._custom_button_callbacks)
if not self._setup:
if self._alerts_layout.active_alerts() > 0:
@@ -153,6 +160,19 @@ class MiciMainLayout(Scroller):
msg = messaging.new_message(service, valid=True)
self._pm.send(service, msg)
@staticmethod
def _toggle_quiet_mode():
ui_state.params.put_bool('QuietMode', not ui_state.params.get_bool('QuietMode'))
def _show_layout(self, layout: Widget):
if gui_app.widget_in_stack(self._onboarding_window):
return
gui_app.pop_widgets_to(self, lambda: self._scroll_to(layout))
def _show_settings(self):
if not gui_app.widget_in_stack(self._onboarding_window):
gui_app.push_widget(self._settings_layout)
def _on_body_changed(self):
self._car_onroad_layout.set_visible(not ui_state.is_body)
self._body_onroad_layout.set_visible(bool(ui_state.is_body))
@@ -7,9 +7,12 @@ class CustomButtonAction(IntEnum):
NONE = 0
BOOKMARK = 1
QUIET_MODE = 2
ONROAD = 3
HOME = 4
SETTINGS = 5
def handle_custom_button(sm, params, bookmark_callback):
def handle_custom_button(sm, params, callbacks):
if not sm.updated['carState']:
return
@@ -18,8 +21,6 @@ def handle_custom_button(sm, params, bookmark_callback):
if not custom_pressed:
return
action = CustomButtonAction(params.get('SteeringCustomButtonMapping', return_default=True))
if action == CustomButtonAction.BOOKMARK:
bookmark_callback()
elif action == CustomButtonAction.QUIET_MODE:
params.put_bool('QuietMode', not params.get_bool('QuietMode'))
action = CustomButtonAction(params.get('CustomButtonAction', return_default=True))
if callback := callbacks.get(action):
callback()
@@ -17,19 +17,15 @@ class FakeSubMaster:
def test_custom_button_actions():
params = Mock()
params.get_bool.return_value = False
sm = FakeSubMaster({
'carState': SimpleNamespace(buttonEvents=[SimpleNamespace(
type=car.CarState.ButtonEvent.Type.altButton2,
pressed=True,
)]),
})
bookmark_callback = Mock()
callbacks = {action: Mock() for action in CustomButtonAction if action != CustomButtonAction.NONE}
params.get.return_value = CustomButtonAction.BOOKMARK
handle_custom_button(sm, params, bookmark_callback)
bookmark_callback.assert_called_once()
params.get.return_value = CustomButtonAction.QUIET_MODE
handle_custom_button(sm, params, bookmark_callback)
params.put_bool.assert_called_once_with('QuietMode', True)
for action, callback in callbacks.items():
params.get.return_value = action
handle_custom_button(sm, params, callbacks)
callback.assert_called_once()
@@ -2173,7 +2173,7 @@
"description": "",
"items": [
{
"key": "SteeringCustomButtonMapping",
"key": "CustomButtonAction",
"widget": "multiple_button",
"title": "Steering Custom Button",
"description": "Choose the openpilot action for the steering wheel custom/star button. OEM functionality is unchanged.",
@@ -2189,6 +2189,18 @@
{
"value": 2,
"label": "Quiet Mode"
},
{
"value": 3,
"label": "Onroad"
},
{
"value": 4,
"label": "Home"
},
{
"value": 5,
"label": "Settings"
}
]
},
@@ -10,7 +10,7 @@ sections:
title: Hyundai / Kia / Genesis Settings
description: ''
items:
- key: SteeringCustomButtonMapping
- key: CustomButtonAction
widget: multiple_button
title: Steering Custom Button
description: Choose the openpilot action for the steering wheel custom/star button. OEM functionality is unchanged.
@@ -21,6 +21,12 @@ sections:
label: Bookmark
- value: 2
label: Quiet Mode
- value: 3
label: Onroad
- value: 4
label: Home
- value: 5
label: Settings
- key: HyundaiLongitudinalTuning
widget: multiple_button
title: Custom Longitudinal Tuning