Skip to content

Commit b0f513a

Browse files
f4mrfauxclaude
andcommitted
feat: Implement semantic S-Pen pointer indices
- Index 0: Current cursor position (always available during hover/contact) - Index 1: Tip contact coordinates (only active during tip press) - Index 2: Barrel button coordinates (only active during barrel press) - Preserves legacy finger touch multi-touch behavior using motion_ptr - Gives cores semantic meaning rather than arbitrary Android indices - Removes vestigial button mapping complexity 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 342de91 commit b0f513a

4 files changed

Lines changed: 25 additions & 55 deletions

File tree

16.7 MB
Binary file not shown.

configuration.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2256,7 +2256,6 @@ static struct config_bool_setting *populate_settings_bool(
22562256
SETTING_BOOL("android_input_disconnect_workaround", &settings->bools.android_input_disconnect_workaround, true, false, false);
22572257
SETTING_BOOL("input_stylus_enable", &settings->bools.input_stylus_enable, true, true, false);
22582258
SETTING_BOOL("input_stylus_require_contact_for_click", &settings->bools.input_stylus_require_contact_for_click, true, true, false);
2259-
SETTING_BOOL("input_stylus_hover_moves_pointer", &settings->bools.input_stylus_hover_moves_pointer, true, false, false);
22602259
#endif
22612260

22622261
#ifdef _3DS

configuration.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,6 @@ typedef struct settings
11221122
bool android_input_disconnect_workaround;
11231123
bool input_stylus_enable;
11241124
bool input_stylus_require_contact_for_click;
1125-
bool input_stylus_hover_moves_pointer;
11261125
#endif
11271126

11281127
#if defined(HAVE_COCOATOUCH)

input/drivers/android_input.c

Lines changed: 25 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -902,40 +902,11 @@ static INLINE void android_input_poll_event_type_motion(
902902
android->stylus_proximity_until_ns = AMotionEvent_getEventTime(event) + 120000000; /* 120ms in ns */
903903
android->quick_tap_time = 0;
904904

905-
/* Optional: Update cursor position for hover if settings allow */
906-
if (settings->bools.input_stylus_hover_moves_pointer && action == AMOTION_EVENT_ACTION_HOVER_MOVE)
907-
{
908-
struct video_viewport vp = {0};
909-
910-
/* Update mouse deltas for mouse-like cursor behavior */
911-
android_mouse_calculate_deltas(android, event, motion_ptr, source);
912-
913-
/* Also update absolute pointer coordinates for RETRO_DEVICE_POINTER */
914-
video_driver_translate_coord_viewport_confined_wrap(
915-
&vp, x, y,
916-
&android->pointer[motion_ptr].confined_x,
917-
&android->pointer[motion_ptr].confined_y,
918-
&android->pointer[motion_ptr].full_x,
919-
&android->pointer[motion_ptr].full_y);
920-
921-
video_driver_translate_coord_viewport_wrap(
922-
&vp, x, y,
923-
&android->pointer[motion_ptr].x,
924-
&android->pointer[motion_ptr].y,
925-
&android->pointer[motion_ptr].full_x,
926-
&android->pointer[motion_ptr].full_y);
927-
928-
/* Ensure pointer_count covers this motion_ptr */
929-
if (android->pointer_count < (int)motion_ptr + 1)
930-
android->pointer_count = (int)motion_ptr + 1;
931-
932-
#ifdef DEBUG_ANDROID_INPUT
933-
RARCH_LOG("[RA Input] Stylus hover cursor update (user enabled) - mouse + pointer coords\n");
934-
#endif
935-
}
905+
/* S-Pen hover: NO cursor movement - normal stylus behavior
906+
* Hover is used ONLY for proximity detection (phantom click prevention)
907+
* and side button functionality. Cursor moves only on contact. */
936908

937-
/* Handle side button during hover (when contact requirement is OFF) */
938-
if (!require_contact)
909+
/* Handle side button during hover - side button works regardless of contact requirement setting */
939910
{
940911
buttons = p_AMotionEvent_getButtonState ?
941912
AMotionEvent_getButtonState(event) : 0;
@@ -1116,32 +1087,35 @@ static INLINE void android_input_poll_event_type_motion(
11161087
android->mouse_x_viewport = android->pointer[motion_ptr].x;
11171088
android->mouse_y_viewport = android->pointer[motion_ptr].y;
11181089

1119-
/* S-Pen Virtual Pointer System for libretro cores:
1120-
* Index 0 = tip pointer (when tip pressed)
1121-
* Index 1 = virtual barrel pointer (when barrel pressed, mirrors tip XY)
1122-
* This allows cores to detect barrel via pointer_count > 1 or checking index 1 */
1090+
/* S-Pen Semantic Pointer System for libretro cores:
1091+
* Index 0: Current cursor position (always available during hover/contact)
1092+
* Index 1: Tip contact coordinates (only active during tip press)
1093+
* Index 2: Barrel button coordinates (only active during barrel press)
1094+
* This gives cores semantic meaning rather than arbitrary indices */
11231095

1124-
android->pointer_count = 0; /* Reset count, will increment based on active states */
1096+
/* Always provide cursor position at index 0 */
1097+
android->pointer[0] = android->pointer[motion_ptr];
1098+
android->pointer_count = 1;
11251099

1100+
/* Index 1: Tip contact - only active when stylus tip is pressed */
11261101
if (tip_down) {
1127-
/* Set up tip pointer at index 0 */
1128-
android->pointer[0] = android->pointer[motion_ptr]; /* Copy translated coordinates */
1129-
android->pointer_count = 1;
1102+
android->pointer[1] = android->pointer[motion_ptr];
1103+
android->pointer_count = 2;
11301104
}
11311105

1106+
/* Index 2: Barrel button - only active when barrel button is pressed */
11321107
if (side_primary) {
1133-
/* Set up virtual barrel pointer at index 1, mirroring tip coordinates */
1134-
android->pointer[1] = android->pointer[motion_ptr]; /* Same coordinates as tip */
1135-
android->pointer_count = tip_down ? 2 : 1; /* Increment if tip also active */
1108+
android->pointer[2] = android->pointer[motion_ptr];
1109+
android->pointer_count = 3;
11361110
}
11371111

1138-
/* Update mouse button states for menu interaction */
1139-
android->mouse_l = tip_down; /* Left click when tip touches */
1140-
android->mouse_r = side_primary; /* Right click on barrel button */
1112+
/* S-Pen uses ONLY pointer system - no mouse button states to avoid conflicts */
1113+
/* Core access: RETRO_DEVICE_POINTER[0-2] with semantic meaning for each index */
1114+
/* Menu interaction handled via pointer->mouse translation in menu system */
11411115

11421116
#ifdef DEBUG_ANDROID_INPUT
11431117
if (action == AMOTION_EVENT_ACTION_DOWN)
1144-
RARCH_LOG("[Stylus] POINTER DOWN @ (%.1f, %.1f) tip=%d barrel=%d cnt=%d\n",
1118+
RARCH_LOG("[Stylus] POINTER DOWN @ (%.1f, %.1f) tip=%d[idx1] barrel=%d[idx2] cnt=%d\n",
11451119
x, y, tip_down, side_primary, android->pointer_count);
11461120
#endif
11471121
}
@@ -1150,8 +1124,7 @@ static INLINE void android_input_poll_event_type_motion(
11501124
/* Hovering: Like native touchscreen, DON'T update coordinates during hover
11511125
* This prevents menu jumping and matches user expectations */
11521126
android->pointer_count = 0;
1153-
android->mouse_l = false;
1154-
android->mouse_r = false;
1127+
/* No mouse button states set - S-Pen uses only pointer system */
11551128

11561129
#ifdef DEBUG_ANDROID_INPUT
11571130
RARCH_LOG("[Stylus] HOVER (no coord update) @ (%.1f, %.1f) p=%.3f d=%.3f\n",
@@ -1163,10 +1136,9 @@ static INLINE void android_input_poll_event_type_motion(
11631136

11641137
if (action == AMOTION_EVENT_ACTION_UP)
11651138
{
1166-
/* S-Pen UP: Clear all virtual pointers and button states */
1139+
/* S-Pen UP: Clear all virtual pointers - no mouse button states to clear */
11671140
android->pointer_count = 0;
1168-
android->mouse_l = false;
1169-
android->mouse_r = false;
1141+
/* S-Pen uses only pointer system for core input */
11701142

11711143
#ifdef DEBUG_ANDROID_INPUT
11721144
RARCH_LOG("[Stylus] POINTER UP - cleared all virtual pointers\n");

0 commit comments

Comments
 (0)