Skip to content

[Agent] feat(ds): DS bottom-screen touch coordinate translation (Phase 2)#3503

Open
github-actions[bot] wants to merge 6 commits intodevelopfrom
agent/issue-3374-ds-touch-translation
Open

[Agent] feat(ds): DS bottom-screen touch coordinate translation (Phase 2)#3503
github-actions[bot] wants to merge 6 commits intodevelopfrom
agent/issue-3374-ds-touch-translation

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Summary

  • DeltaSkinView — detect when a touch falls within the NDS bottom-screen viewport (identified via screenGroups[].screens), normalize the touch point within that viewport (0–1 on each axis), and forward it through DeltaSkinInputHandler.ndsBottomScreenTouched(at:). Tracks each touch independently via a touchToNDSScreenMap dictionary so multi-touch behaves correctly.
  • PVMelonDSCore / PVDesmume2015Core — add touchScreenAtPoint(_:) and releaseScreenTouch() forwarding from the Swift layer to the Obj-C bridge.
  • PVMelonDSCoreBridge / PVDesmume2015CoreBridge — implement touchScreenAtPoint: and releaseScreenTouch using the libretro pointer device (setMousePosition: + setLeftMouseButtonPressed:), matching the existing approach in PVThinLibretroCore.

Coordinate flow

User tap on bottom-screen viewport (UIKit touch)
  ↓
DeltaSkinView.handleTouchAtLocation(_:in:touchId:)
  ↓ mapToNDSBottomScreen(_:in:)       [outputFrame → view coords → normalize 0–1]
  ↓
DeltaSkinInputHandler.ndsBottomScreenTouched(at: normalizedPoint)
  ↓ normalizedPoint × 255 / 191      [0–1 → DS hardware coords]
  ↓
PVDSSystemResponderClient.touchScreenAtPoint(_ dsPoint: CGPoint)
  ↓
Core bridge: setMousePosition(normalized) + setLeftMouseButtonPressed(YES)
  ↓
RETRO_DEVICE_POINTER state polled by libretro core

Layout support

Orientation Bottom screen detection
Portrait (stacked) Bottom screen has larger outputFrame.minY
Landscape (side-by-side) Bottom screen has id "nds_bottom" or larger outputFrame.minX

The mapToNDSBottomScreen helper prefers id == "nds_bottom" (set by DefaultDeltaSkin) and falls back to largest-minY screen, which naturally selects the bottom screen in portrait layouts.

Test plan

  • Launch a DS ROM with melonDS → tap bottom screen → confirm stylus input reaches game
  • Launch a DS ROM with DeSmuME 2015 → same
  • Launch a DS ROM via RetroArch thin core → same
  • Drag across bottom screen → confirm moved events track correctly
  • Lift finger → confirm releaseScreenTouch is called
  • Multi-touch: hold button + tap screen simultaneously → both work
  • Tap top screen → no touchscreen event forwarded
  • Landscape orientation → side-by-side screens → bottom-right screen responds
  • Non-DS game → no regression in touch handling

Notes

Part of #3374
Depends on: #3377

@github-actions github-actions bot requested a review from JoeMatt as a code owner March 25, 2026 07:51
github-actions bot added a commit that referenced this pull request Mar 25, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot enabled auto-merge (squash) March 25, 2026 07:52
@github-actions github-actions bot added agent-work PR or issue being worked on by the AI agent ai-reviewing AI code review in progress labels Mar 25, 2026
@github-actions
Copy link
Copy Markdown
Contributor Author

🤖 PR created. AI review starting automatically.

@JoeMatt JoeMatt requested a review from Copilot March 25, 2026 08:13
@github-actions github-actions bot removed the ai-reviewing AI code review in progress label Mar 25, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Nintendo DS bottom-screen touch support to the DeltaSkin dual-screen pipeline by mapping UIKit touches inside the bottom-screen viewport into DS hardware coordinates and forwarding them into each DS core’s libretro pointer input path.

Changes:

  • Detect bottom-screen touches in DeltaSkinView, normalize them to 0–1 within the bottom screen, and forward begin/move/release events via DeltaSkinInputHandler.
  • Add DS touchscreen forwarding methods in the Swift core layers for melonDS and DeSmuME 2015.
  • Implement DS touchscreen input in the Obj-C++ libretro bridges by driving pointer position + pressed state.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
PVUI/Sources/PVUIBase/SwiftUI/DeltaSkins/Views/DeltaSkinView.swift Tracks DS bottom-screen touches and maps touch locations into bottom-screen-normalized coordinates.
Cores/melonDS/PVMelonDSCore/Core/PVMelonDSCore.swift Forwards DS touchscreen events from Swift core to Obj-C bridge.
Cores/melonDS/PVMelonDSCore/Core/PVMelonDSCore+Controls.mm Implements DS touchscreen via libretro pointer/mouse bridge calls.
Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core.swift Forwards DS touchscreen events from Swift core to Obj-C bridge.
Cores/Desmume2015/PVDesmume2015Core/Core/PVDesmume2015Core+Controls.mm Implements DS touchscreen via libretro pointer/mouse bridge calls.
.changelog/3503.md Adds changelog entry for DS dual-screen touch coordinate translation.

Comment on lines +1269 to +1272
// Touch dragged off the bottom screen — release and fall through to button detection
DLOG("DS bottom screen touch left screen area, releasing")
touchToNDSScreenMap.removeValue(forKey: touchId)
inputHandler.ndsBottomScreenTouchReleased()
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When an NDS screen touch drags outside the bottom-screen frame, this unconditionally calls ndsBottomScreenTouchReleased(). If another finger is still touching the bottom screen, this will incorrectly release the stylus for all touches. Consider only calling release when the last active screen-touch ID is removed (same logic as the .ended path), or track an active-touch count and release only when it reaches zero.

Suggested change
// Touch dragged off the bottom screen — release and fall through to button detection
DLOG("DS bottom screen touch left screen area, releasing")
touchToNDSScreenMap.removeValue(forKey: touchId)
inputHandler.ndsBottomScreenTouchReleased()
// Touch dragged off the bottom screen — potentially release and fall through to button detection
DLOG("DS bottom screen touch left screen area for touchId=\(touchId), removing mapping")
touchToNDSScreenMap.removeValue(forKey: touchId)
// Only release when this was the last active NDS bottom-screen touch
if touchToNDSScreenMap.isEmpty {
DLOG("No remaining DS bottom screen touches, releasing stylus")
inputHandler.ndsBottomScreenTouchReleased()
}

Copilot uses AI. Check for mistakes.
Comment on lines +1599 to +1604
let (scaleX, scaleY, xOffset, yOffset) = calculateButtonTransform(in: size, mappingSize: mappingSize)
let scaledFrame = CGRect(
x: outputFrame.minX * scaleX + xOffset,
y: yOffset + outputFrame.minY * scaleY,
width: outputFrame.width * scaleX,
height: outputFrame.height * scaleY
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mapToNDSBottomScreen scales outputFrame using calculateButtonTransform, which assumes outputFrame is in mappingSize pixel coordinates. For skins where outputFrame is already normalized (0–1) — e.g. DefaultDeltaSkin uses outputFrame.x = 0.31 — this produces a ~sub-point scaledFrame and bottom-screen touch detection will never trigger. Suggest normalizing outputFrame first (if any component > 1, divide by mappingSize; otherwise treat as already-normalized), then convert to view coordinates using the same layout math used for screen rendering (layout width/height + offsets, including safe-area insets).

Suggested change
let (scaleX, scaleY, xOffset, yOffset) = calculateButtonTransform(in: size, mappingSize: mappingSize)
let scaledFrame = CGRect(
x: outputFrame.minX * scaleX + xOffset,
y: yOffset + outputFrame.minY * scaleY,
width: outputFrame.width * scaleX,
height: outputFrame.height * scaleY
// Normalize outputFrame into 0–1 space if it is specified in mappingSize pixels.
// Some skins (e.g. DefaultDeltaSkin) already use normalized coordinates (0–1),
// while others may specify absolute positions in the skin's mapping space.
let isPixelBased = outputFrame.maxX > 1 || outputFrame.maxY > 1
let normalizedFrame: CGRect
if isPixelBased, mappingSize.width > 0, mappingSize.height > 0 {
normalizedFrame = CGRect(
x: outputFrame.minX / mappingSize.width,
y: outputFrame.minY / mappingSize.height,
width: outputFrame.width / mappingSize.width,
height: outputFrame.height / mappingSize.height
)
} else {
normalizedFrame = outputFrame
}
// Convert normalized frame back into mapping-space pixels so that
// calculateButtonTransform (which works in mappingSize coordinates)
// can be applied consistently for both normalized and pixel-based skins.
let mappingFrame = CGRect(
x: normalizedFrame.minX * mappingSize.width,
y: normalizedFrame.minY * mappingSize.height,
width: normalizedFrame.width * mappingSize.width,
height: normalizedFrame.height * mappingSize.height
)
let (scaleX, scaleY, xOffset, yOffset) = calculateButtonTransform(in: size, mappingSize: mappingSize)
let scaledFrame = CGRect(
x: mappingFrame.minX * scaleX + xOffset,
y: yOffset + mappingFrame.minY * scaleY,
width: mappingFrame.width * scaleX,
height: mappingFrame.height * scaleY

Copilot uses AI. Check for mistakes.
@State private var processedTouches: Set<ObjectIdentifier> = []

// Track touch IDs that are actively touching the NDS bottom screen (for continuous updates and release)
@State private var touchToNDSScreenMap: [ObjectIdentifier: Bool] = [:]
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

touchToNDSScreenMap only uses the key presence (!= nil) and always stores true, so a Set<ObjectIdentifier> would communicate intent more clearly and avoid carrying an unused Bool payload.

Suggested change
@State private var touchToNDSScreenMap: [ObjectIdentifier: Bool] = [:]
@State private var ndsScreenTouches: Set<ObjectIdentifier> = []

Copilot uses AI. Check for mistakes.
Comment on lines +292 to +293
CGFloat normalizedX = point.x / 255.0;
CGFloat normalizedY = point.y / 191.0;
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pointer normalization here uses / 255.0 and / 191.0, while PVThinLibretroCore.touchScreenAtPoint uses / 256.0 and / 192.0 for DS (treating the resolution as 256×192). This difference will make edge touches map slightly differently across DS core paths. Consider aligning the normalization formula with the thin-core path (and/or libretro pointer expectations) so touch behavior is consistent between melonDS/desmume bridges and RetroArch DS cores.

Suggested change
CGFloat normalizedX = point.x / 255.0;
CGFloat normalizedY = point.y / 191.0;
CGFloat normalizedX = point.x / 256.0;
CGFloat normalizedY = point.y / 192.0;

Copilot uses AI. Check for mistakes.
Comment on lines +291 to +293
// Normalize to 0.0-1.0 for the libretro pointer state used by RETRO_DEVICE_POINTER
CGFloat normalizedX = point.x / 255.0;
CGFloat normalizedY = point.y / 191.0;
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pointer normalization here uses / 255.0 and / 191.0, while PVThinLibretroCore.touchScreenAtPoint uses / 256.0 and / 192.0 for DS (treating the resolution as 256×192). This difference will make edge touches map slightly differently across DS core paths. Consider aligning the normalization formula with the thin-core path (and/or libretro pointer expectations) so touch behavior is consistent between desmume2015 bridge and RetroArch DS cores.

Suggested change
// Normalize to 0.0-1.0 for the libretro pointer state used by RETRO_DEVICE_POINTER
CGFloat normalizedX = point.x / 255.0;
CGFloat normalizedY = point.y / 191.0;
// Normalize to 0.0-1.0 for the libretro pointer state used by RETRO_DEVICE_POINTER,
// matching PVThinLibretroCore (treating the resolution as 256x192)
CGFloat normalizedX = point.x / 256.0;
CGFloat normalizedY = point.y / 192.0;

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor Author

github-actions bot commented Mar 25, 2026

✅ Copilot Review Audit — Complete

Progress

  • 🚀 Agent started
  • 📖 Read all Copilot review comments (13 total across 4 review passes)
  • 🔍 Evaluated each comment
  • 🔨 Applied 3 fixes (spam notifications, duplicate import)
  • 📤 Pushed to branch

Fixes Applied

Issue Status
setLeftMouseButtonPressed:YES spam on drag (melonDS) ✅ Fixed — guard with ndsTouchActive ivar
setLeftMouseButtonPressed:YES spam on drag (DeSmuME) ✅ Fixed — guard with ndsTouchActive ivar
Duplicate @import PVCoreBridge ✅ Fixed — removed duplicate

Already Correct (no changes needed)

  • Multi-touch release guard (ndsScreenTouches.isEmpty) ✅
  • Coordinate normalization (/256.0, /192.0) ✅
  • Set<ObjectIdentifier> vs unused Dict<_, Bool>
  • Landscape bottom-screen fallback (minX tiebreaker) ✅
  • Forced cast consistency in Swift wrappers ✅
  • Fall-through to button detection after leaving screen ✅
  • Changelog trailing period (already absent) ✅

Completed: 2026-03-25 UTC

@github-actions
Copy link
Copy Markdown
Contributor Author

✅ Fixes pushed — addressed all 5 Copilot review comments:

  1. Touch-off-screen release: Only calls ndsBottomScreenTouchReleased() when the last active NDS screen touch leaves the area (not on every drag-out)
  2. outputFrame normalization: mapToNDSBottomScreen now detects pixel-based vs normalized outputFrame and normalizes first before applying calculateButtonTransform, fixing touch detection for skins like DefaultDeltaSkin
  3. Set instead of Dict: Replaced touchToNDSScreenMap: [ObjectIdentifier: Bool] with ndsScreenTouches: Set<ObjectIdentifier> — cleaner intent, no unused Bool payload
  4. melonDS normalization: Fixed /255.0/256.0 and /191.0/192.0 to match PVThinLibretroCore
  5. DeSmuME 2015 normalization: Same fix — /255.0/256.0 and /191.0/192.0

@github-actions github-actions bot added the ai-reviewing AI code review in progress label Mar 25, 2026
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from d91279a to f80b153 Compare March 25, 2026 08:45
github-actions bot added a commit that referenced this pull request Mar 25, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor Author

⚠️ Merge dependency not yet satisfied — this PR has a Depends on: #N link to an open PR. Merge order matters to avoid conflicts. The dependency check is advisory only — merging is still allowed.

@github-actions github-actions bot added the blocked Blocked by another open issue or PR label Mar 25, 2026
@JoeMatt
Copy link
Copy Markdown
Member

JoeMatt commented Mar 25, 2026

@claude please audit all Copilot review comments on this PR. For each comment:

  1. Evaluate whether the concern is valid
  2. Fix any valid issues (compile errors, logic bugs, missing null checks, incorrect API usage, etc.)
  3. Note/dismiss nits that are style-only with a brief explanation

After addressing the review comments, do a self-review pass:

  • Verify all changed files compile (check for unresolved symbols, missing imports, type mismatches)
  • Check for any dead code, unused variables, or missing test coverage
  • Ensure multi-platform compatibility (iOS + tvOS + macOS Catalyst)

Then re-request Copilot review.

@github-actions
Copy link
Copy Markdown
Contributor Author

🔍 Copilot Review Audit — All Issues Already Addressed

I audited all 5 Copilot inline review comments on this PR. All were fixed in commit f80b1539e (prior fix pass). Summary below:

Copilot Comment Audit

# File Concern Status
1 DeltaSkinView.swift:1272 Multi-touch bug: unconditional stylus release when dragging off-screen ✅ Fixed — ndsScreenTouches.remove(touchId) + if ndsScreenTouches.isEmpty { release() }
2 DeltaSkinView.swift:1604 outputFrame normalization: some skins use 0–1 coords, others use pixel coords ✅ Fixed — `isPixelBased = outputFrame.maxX > 1
3 DeltaSkinView.swift:122 Use Set<ObjectIdentifier> instead of [ObjectIdentifier: Bool] ✅ Done — @State private var ndsScreenTouches: Set<ObjectIdentifier> = []
4 PVMelonDSCore+Controls.mm:293 Normalization: /255.0//191.0 -> /256.0//192.0 to match thin-core path ✅ Fixed — point.x / 256.0, point.y / 192.0
5 PVDesmume2015Core+Controls.mm:293 Same normalization issue as melonDS ✅ Fixed — same

Self-Review Findings

Architecture correctness: Verified the full data path:

  • DeltaSkinInputHandler.ndsBottomScreenTouched(at:) normalizes 0–1 → DS pixels (0–255, 0–191)
  • Native bridge touchScreenAtPoint: uses setMousePosition: + setLeftMouseButtonPressed:YES
  • PVLibRetroCore.m RETRO_DEVICE_POINTER handler reads currentTouchPosition (set by setMousePosition:) — correct, not the _pointerX/_pointerY path used by PVThinLibretroFrontend

Normalization math: Using /256.0 and /192.0 is consistent with PVThinLibretroCore.touchScreenAtPoint and correct for the libretro pointer model (256-cell grid where pixel 255 is at normalized 255/256, not 1.0).

Protocol conformance: Both PVMelonDSCoreBridge and PVDesmume2015CoreBridge declare <PVDSSystemResponderClient> in their class headers and implement touchScreenAtPoint: + releaseScreenTouch in their Controls categories.

Multi-platform: All NDS touch code is either inside #if !os(tvOS) gesture blocks or in private helper functions that compile on all platforms (using only CGPoint/CGRect/Set). No tvOS-incompatible APIs introduced.

Pre-existing issue noted (not from this PR): PVMelonDSCore+Controls.mm has a duplicate @import PVCoreBridge; on lines 11–12 (pre-dates this PR, harmless in ObjC).

No new commits needed — all Copilot issues were already resolved.

@github-actions github-actions bot removed the ai-reviewing AI code review in progress label Mar 25, 2026
@JoeMatt JoeMatt requested a review from Copilot March 25, 2026 19:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

@@ -0,0 +1,2 @@
### Added
- **DS Dual-Screen Touch Coordinate Translation** — Tapping the bottom-screen viewport in a Nintendo DS dual-screen skin now sends correctly translated hardware coordinates (0–255 x, 0–191 y) to the emulator core via `PVDSSystemResponderClient`. Supports touch began, moved, and ended for melonDS, DeSmuME 2015, and RetroArch DS cores in both portrait (stacked) and landscape (side-by-side) layouts.
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changelog fragments should be plain English with no trailing period. This entry ends with a period; please remove the final punctuation to match the repository changelog style.

Suggested change
- **DS Dual-Screen Touch Coordinate Translation** — Tapping the bottom-screen viewport in a Nintendo DS dual-screen skin now sends correctly translated hardware coordinates (0–255 x, 0–191 y) to the emulator core via `PVDSSystemResponderClient`. Supports touch began, moved, and ended for melonDS, DeSmuME 2015, and RetroArch DS cores in both portrait (stacked) and landscape (side-by-side) layouts.
- **DS Dual-Screen Touch Coordinate Translation** — Tapping the bottom-screen viewport in a Nintendo DS dual-screen skin now sends correctly translated hardware coordinates (0–255 x, 0–191 y) to the emulator core via `PVDSSystemResponderClient`. Supports touch began, moved, and ended for melonDS, DeSmuME 2015, and RetroArch DS cores in both portrait (stacked) and landscape (side-by-side) layouts

Copilot uses AI. Check for mistakes.
Comment on lines +1275 to +1279
inputHandler.ndsBottomScreenTouchReleased()
}
}
return
}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a touch that started as an NDS screen touch moves off the bottom-screen area, the comment says it should “fall through to button detection”, but the function always returns immediately. This prevents that touch from ever transitioning to button/D-pad handling after leaving the screen. Consider only returning early when the touch remains within the bottom screen; if it leaves, remove it from ndsScreenTouches/release stylus and continue through the normal button hit-testing path (or update the comment to match intended behavior).

Copilot uses AI. Check for mistakes.
Comment on lines +1594 to +1599
// Prefer explicit id; fall back to the screen with the largest minY (portrait-stacked bottom)
let bottomScreen: DeltaSkinScreen? = allScreens.first { $0.id == "nds_bottom" }
?? allScreens.compactMap { screen -> (DeltaSkinScreen, CGFloat)? in
guard let frame = screen.outputFrame else { return nil }
return (screen, frame.minY)
}.max(by: { $0.1 < $1.1 })?.0
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mapToNDSBottomScreen’s fallback selection uses only the largest outputFrame.minY. In side-by-side (landscape) layouts where both screens share the same minY, this can pick the wrong screen when the explicit id == "nds_bottom" isn’t present. Consider adding a landscape-safe fallback (e.g., choose the screen with the largest minX when minY ties, or sort by (minY, minX)).

Suggested change
// Prefer explicit id; fall back to the screen with the largest minY (portrait-stacked bottom)
let bottomScreen: DeltaSkinScreen? = allScreens.first { $0.id == "nds_bottom" }
?? allScreens.compactMap { screen -> (DeltaSkinScreen, CGFloat)? in
guard let frame = screen.outputFrame else { return nil }
return (screen, frame.minY)
}.max(by: { $0.1 < $1.1 })?.0
// Prefer explicit id; fall back to the screen with the largest minY (portrait-stacked bottom),
// and when minY ties (e.g., side-by-side landscape), choose the one with the largest minX.
let bottomScreen: DeltaSkinScreen? = allScreens.first { $0.id == "nds_bottom" }
?? allScreens.compactMap { screen -> (DeltaSkinScreen, CGRect)? in
guard let frame = screen.outputFrame else { return nil }
return (screen, frame)
}.max(by: { lhs, rhs in
if lhs.1.minY == rhs.1.minY {
return lhs.1.minX < rhs.1.minX
}
return lhs.1.minY < rhs.1.minY
})?.0

Copilot uses AI. Check for mistakes.
@github-actions github-actions bot added the needs-fixes AI review found issues; auto-fixer dispatched label Mar 25, 2026
@github-actions
Copy link
Copy Markdown
Contributor Author

✅ Fixes pushed — addressed all Copilot review comments:

  1. Fall-through on screen-exit: Touch that drags off the NDS bottom screen now falls through to button/D-pad hit-testing instead of returning early. The return was moved inside the "still on screen" branch.
  2. Landscape bottom-screen fallback: Added minX tiebreaker in mapToNDSBottomScreen — when two screens share the same minY (side-by-side landscape), the screen with the larger minX is selected as the bottom screen.
  3. Changelog style: Removed trailing period from .changelog/3503.md to match project style.

Notes: The Set<ObjectIdentifier> refactor, outputFrame normalization, and 256×192 division were already applied in a prior commit.

@github-actions github-actions bot added ai-reviewing AI code review in progress and removed needs-fixes AI review found issues; auto-fixer dispatched ai-reviewing AI code review in progress labels Mar 25, 2026
@JoeMatt JoeMatt requested a review from Copilot March 25, 2026 21:53
github-actions bot added a commit that referenced this pull request Mar 28, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from fe980e8 to 2b009be Compare March 28, 2026 05:57
github-actions bot added a commit that referenced this pull request Mar 28, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from 2b009be to fabbb6f Compare March 28, 2026 08:28
github-actions bot added a commit that referenced this pull request Mar 28, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from fabbb6f to f535bf0 Compare March 28, 2026 19:50
github-actions bot added a commit that referenced this pull request Mar 28, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from f535bf0 to 90c1273 Compare March 28, 2026 21:38
github-actions bot added a commit that referenced this pull request Mar 28, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from 90c1273 to 28b40c4 Compare March 28, 2026 23:00
github-actions bot added a commit that referenced this pull request Mar 28, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from 28b40c4 to 7bf2c0b Compare March 28, 2026 23:14
github-actions bot added a commit that referenced this pull request Mar 29, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from 7bf2c0b to 0ff9368 Compare March 29, 2026 01:14
github-actions bot added a commit that referenced this pull request Mar 29, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from 0ff9368 to f004378 Compare March 29, 2026 20:58
github-actions bot added a commit that referenced this pull request Mar 29, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from f004378 to 2f8ff50 Compare March 29, 2026 22:46
github-actions bot added a commit that referenced this pull request Mar 30, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from 2f8ff50 to b1077c2 Compare March 30, 2026 01:06
github-actions bot added a commit that referenced this pull request Mar 30, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from b1077c2 to c1aed24 Compare March 30, 2026 01:53
github-actions bot added a commit that referenced this pull request Mar 31, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot force-pushed the agent/issue-3374-ds-touch-translation branch from c1aed24 to 8c93fff Compare March 31, 2026 00:34
github-actions bot and others added 6 commits April 4, 2026 02:02
Map taps on the NDS bottom-screen viewport to DS hardware coordinates
(0-255 x, 0-191 y) and forward them to the core via
PVDSSystemResponderClient.touchScreenAtPoint(_:)/releaseScreenTouch().

Changes:
- DeltaSkinView: detect NDS bottom-screen touches using screen group
  outputFrame data, track them per-touch-ID, and route through
  DeltaSkinInputHandler.ndsBottomScreenTouched(at:). Supports both
  portrait (stacked) and landscape (side-by-side) dual-screen layouts.
- PVMelonDSCore/PVDesmume2015Core: forward touchScreenAtPoint and
  releaseScreenTouch calls to the Obj-C bridge.
- PVMelonDSCoreBridge/PVDesmume2015CoreBridge: implement touchscreen
  methods using the libretro pointer device (setMousePosition +
  setLeftMouseButtonPressed) — same mechanism as PVThinLibretroCore.

Part of #3374 (DS Dual-Screen Touch)
Depends on: #3377 (skin loading must be enabled first)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…elog

- Allow touch that leaves NDS bottom screen to fall through to button
  hit-testing instead of unconditionally returning early
- Add minX tiebreaker in mapToNDSBottomScreen for landscape (side-by-side)
  layouts where both screens share the same minY
- Remove trailing period from changelog fragment per project style

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use (_bridge as! PVDSSystemResponderClient) instead of optional cast
so bridge conformance regressions fail loudly, consistent with
didPush/didRelease pattern.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add `ndsTouchActive` ivar to melonDS and DeSmuME 2015 bridge headers
- Guard `setLeftMouseButtonPressed:YES` so it fires only on touch-down,
  not on every move update (avoids spamming PVMouseButtonDidPress)
- Remove duplicate `@import PVCoreBridge` in PVMelonDSCore+Controls.mm

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-work PR or issue being worked on by the AI agent blocked Blocked by another open issue or PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants