Skip to content

[Feature] DS Dual-Screen: Touch coordinate translation for bottom screen #3374

Description

@github-actions

Summary

DS bottom screen is a touchscreen. When a user taps the bottom-screen viewport in a dual-screen skin, the touch coordinates must be translated from skin-space into DS hardware coordinates (0–255 x, 0–191 y) before being forwarded to the core via PVDSSystemResponderClient.

Background

The existing PVDSSystemResponderClient protocol has:

func touchBegan(at point: CGPoint)
func touchMoved(at point: CGPoint)
func touchEnded()

Where point is expected in DS hardware coordinates (x: 0–255, y: 0–191).

Currently, touch events from the on-screen emulator view are passed directly to the core without any skin-aware coordinate mapping. With dual-screen skins, the bottom-screen output frame is a sub-region of the full view — touch points must be mapped:

viewTouchPoint → (normalize by bottomScreenOutputFrame) → dsX = normalizedX * 255, dsY = normalizedY * 191

Required Work

  1. Detect bottom-screen touches — In DeltaSkinInputHandler or MultiTouchView, identify taps that fall within the bottom-screen output frame.

  2. Coordinate transform:

    func mapToDS(touch: CGPoint, bottomScreenFrame: CGRect) -> CGPoint? {
        guard bottomScreenFrame.contains(touch) else { return nil }
        let normalizedX = (touch.x - bottomScreenFrame.minX) / bottomScreenFrame.width
        let normalizedY = (touch.y - bottomScreenFrame.minY) / bottomScreenFrame.height
        return CGPoint(x: normalizedX * 255, y: normalizedY * 191)
    }
  3. Forward to core — Pass mapped coordinates to PVDSSystemResponderClient.touchBegan(at:) etc.

  4. Block non-skin-aware path — Ensure the old direct-passthrough path is disabled when a dual-screen NDS skin is active (to avoid double-forwarding).

Files to Change

  • PVUI/Sources/PVUIBase/SwiftUI/DeltaSkins/Models/DeltaSkinInputHandler.swift
  • PVUI/Sources/PVUIBase/SwiftUI/DeltaSkins/Views/MultiTouchView.swift
  • PVUI/Sources/PVUIBase/PVEmulatorVC/PVEmulatorViewController+DualScreen.swift

Acceptance Criteria

  • Tapping the bottom screen viewport in an NDS skin sends correct DS coordinates to the core
  • Tapping the top screen area does NOT trigger touchscreen events
  • Touch tracking (began/moved/ended) is correctly forwarded
  • Screen-swap mode (when active) swaps which viewport is treated as touch

Depends on

#[Metal sub-rectangle issue number] — touch regions are only meaningful once screens render at correct positions

Part of

Part of #2540 — DS Dual-Screen Skin System

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementimprovements, enhancements, new features, additions

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions