diff --git a/movement.c b/movement.c index c1a5d087..34e5645e 100644 --- a/movement.c +++ b/movement.c @@ -61,6 +61,11 @@ watch_date_time_t scheduled_tasks[MOVEMENT_NUM_FACES]; const int32_t movement_le_inactivity_deadlines[8] = {INT_MAX, 600, 3600, 7200, 21600, 43200, 86400, 604800}; const int16_t movement_timeout_inactivity_deadlines[4] = {60, 120, 300, 1800}; +const uint32_t _movement_mode_button_events_mask = 0b1111 << EVENT_MODE_BUTTON_DOWN; +const uint32_t _movement_light_button_events_mask = 0b1111 << EVENT_LIGHT_BUTTON_DOWN; +const uint32_t _movement_alarm_button_events_mask = 0b1111 << EVENT_ALARM_BUTTON_DOWN; +const uint32_t _movement_button_events_mask = _movement_mode_button_events_mask | _movement_light_button_events_mask | _movement_alarm_button_events_mask; + typedef struct { movement_event_type_t down_event; watch_cb_t cb_longpress; @@ -93,6 +98,9 @@ typedef struct { movement_button_t mode_button; movement_button_t light_button; movement_button_t alarm_button; + + // button events that will not be passed to the current face loop, but will instead passed directly to the default loop handler. + volatile uint32_t passthrough_events; } movement_volatile_state_t; movement_volatile_state_t movement_volatile_state; @@ -278,6 +286,12 @@ static void _movement_handle_button_presses(uint32_t pending_events) { &movement_volatile_state.alarm_button }; + uint32_t button_events_masks[3] = { + _movement_mode_button_events_mask, + _movement_light_button_events_mask, + _movement_alarm_button_events_mask, + }; + for (uint8_t i = 0; i < 3; i++) { movement_button_t* button = buttons[i]; @@ -285,6 +299,8 @@ static void _movement_handle_button_presses(uint32_t pending_events) { if (pending_events & (1 << button->down_event)) { watch_rtc_register_comp_callback_no_schedule(button->cb_longpress, button->down_timestamp + MOVEMENT_LONG_PRESS_TICKS, button->timeout_index); any_down = true; + // this button's events will start getting passed to the face + movement_volatile_state.passthrough_events &= ~button_events_masks[i]; } // If a button up or button long up occurred @@ -1173,6 +1189,9 @@ static bool _switch_face(void) { movement_state.watch_face_changed = false; bool can_sleep = wf->loop(event, watch_face_contexts[movement_state.current_face_idx]); + // Button events that follow a down event that happened on the previous face should not be forwarded to the new face + movement_volatile_state.passthrough_events = _movement_button_events_mask; + return can_sleep; } @@ -1221,7 +1240,19 @@ bool app_loop(void) { } // Consume all the pending events + uint32_t passthrough_pending_events = pending_events & movement_volatile_state.passthrough_events; + pending_events = pending_events & ~movement_volatile_state.passthrough_events; + movement_event_type_t event_type = 0; + while (passthrough_pending_events) { + uint8_t next_event = __builtin_ctz(passthrough_pending_events); + event.event_type = event_type + next_event; + can_sleep = movement_default_loop_handler(event) && can_sleep; + passthrough_pending_events = passthrough_pending_events >> (next_event + 1); + event_type = event_type + next_event + 1; + } + + event_type = 0; while (pending_events) { uint8_t next_event = __builtin_ctz(pending_events); event.event_type = event_type + next_event;