feat(android): long-press opens radial menu as right-click alternative
Touch screens have no right mouse button, so right-click radial was inaccessible on Android. New system radial_open_on_long_press counts up while a touch is held on a face-up card without crossing the drag threshold; after 0.5 s it transitions RightClickRadialState to Active, which the existing visual overlay and destination-ring infrastructure then renders unchanged. Three supporting changes to wire up the touch-driven confirm path: - radial_track_cursor: falls back to the first active Touches position when cursor_world returns None, so the hover ring tracks a sliding held finger on Android. - radial_handle_release_or_cancel: confirms on Touches::iter_just_released (finger lift) in addition to right-mouse release. Cancels on Touches::iter_just_canceled. No new event reader — uses the Touches resource which is already in scope after the track_cursor addition. - handle_double_tap: skips when the radial is active. Guards the narrow edge case where the finger lifts on the exact same frame as the 0.5 s long-press threshold fires; prevents a spurious double-tap move from racing with the radial confirm. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,7 @@ use solitaire_core::rules::{can_place_on_foundation, can_place_on_tableau};
|
||||
use crate::card_animation::tuning::AnimationTuning;
|
||||
use crate::card_animation::{CardAnimation, MotionCurve};
|
||||
use crate::card_plugin::{CardEntity, HintHighlight, HintHighlightTimer, STACK_FAN_FRAC};
|
||||
use crate::radial_menu::RightClickRadialState;
|
||||
use crate::ui_theme::{MOTION_DRAG_REJECT_SECS, STATE_SUCCESS, STATE_WARNING};
|
||||
use solitaire_core::game_state::DrawMode;
|
||||
use crate::challenge_plugin::CHALLENGE_UNLOCK_LEVEL;
|
||||
@@ -1413,6 +1414,7 @@ fn handle_double_click(
|
||||
fn handle_double_tap(
|
||||
mut touch_events: MessageReader<TouchInput>,
|
||||
paused: Option<Res<PausedResource>>,
|
||||
radial: Option<Res<RightClickRadialState>>,
|
||||
time: Res<Time>,
|
||||
drag: Res<DragState>,
|
||||
game: Res<GameStateResource>,
|
||||
@@ -1425,6 +1427,11 @@ fn handle_double_tap(
|
||||
if paused.is_some_and(|p| p.0) {
|
||||
return;
|
||||
}
|
||||
// Long-press opened the radial in this frame — let radial_handle_release_or_cancel
|
||||
// own the finger-lift event instead.
|
||||
if radial.is_some_and(|r| r.is_active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only active when a touch is tracked and hasn't crossed the drag threshold.
|
||||
let Some(active_id) = drag.active_touch_id else { return };
|
||||
|
||||
Reference in New Issue
Block a user