Skip to content

Commit e3df894

Browse files
f4mrfauxclaude
andcommitted
android/input: Fix S Pen side button hover click detection
Address side button detection for hover-click functionality: * Fix side button state detection during hover events * Ensure side button logic is properly integrated with hover guard system * Maintain compatibility with existing stylus contact detection * Preserve phantom click prevention during side button operations This commit resolves initial side button detection issues and prepares the foundation for comprehensive drag operation support. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 1611933 commit e3df894

1 file changed

Lines changed: 115 additions & 3 deletions

File tree

input/drivers/android_input.c

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ typedef struct android_input
187187
int64_t quick_tap_time;
188188
bool stylus_proximity_active;
189189
int64_t stylus_proximity_until_ns;
190+
bool stylus_side_button_active; /* Track side button state */
191+
size_t stylus_side_button_ptr; /* Track which pointer index */
190192
state_device_t pad_states[MAX_USERS]; /* int alignment */
191193
int mouse_x, mouse_y;
192194
int16_t mouse_x_viewport_screen, mouse_y_viewport_screen;
@@ -666,6 +668,8 @@ static void *android_input_init(const char *joypad_driver)
666668
android->quick_tap_time = 0;
667669
android->stylus_proximity_active = false;
668670
android->stylus_proximity_until_ns = 0;
671+
android->stylus_side_button_active = false;
672+
android->stylus_side_button_ptr = 0;
669673

670674
input_keymaps_init_keyboard_lut(rarch_key_map_android);
671675

@@ -869,6 +873,18 @@ static INLINE void android_input_poll_event_type_motion(
869873
settings = config_get_ptr();
870874
if (!settings)
871875
return;
876+
877+
/* Check if stylus support is globally disabled */
878+
if (!settings->bools.input_stylus_enable)
879+
{
880+
#ifdef DEBUG_ANDROID_INPUT
881+
RARCH_LOG("[RA Input] Stylus support disabled - ignoring stylus event\n");
882+
#endif
883+
return; /* Treat stylus events as if they never happened */
884+
}
885+
886+
/* Get stylus settings once for all cases */
887+
require_contact = settings->bools.input_stylus_require_contact_for_click;
872888

873889
switch (action)
874890
{
@@ -894,7 +910,104 @@ static INLINE void android_input_poll_event_type_motion(
894910
RARCH_LOG("[RA Input] Stylus hover cursor update (user enabled)\n");
895911
#endif
896912
}
897-
return; /* NEVER allow hover to trigger clicks */
913+
914+
/* Handle side button during hover for DRAG, regardless of click/contact policy */
915+
buttons = p_AMotionEvent_getButtonState ?
916+
AMotionEvent_getButtonState(event) : 0;
917+
side_primary = (buttons & AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) != 0;
918+
side_secondary = (buttons & AMOTION_EVENT_BUTTON_STYLUS_SECONDARY) != 0;
919+
bool side_pressed = side_primary || side_secondary;
920+
921+
#ifdef DEBUG_ANDROID_INPUT
922+
if (buttons != 0)
923+
RARCH_LOG("[Stylus Btn] state=0x%x primary=%d secondary=%d\n",
924+
buttons, !!side_primary, !!side_secondary);
925+
#endif
926+
927+
/* Side button pressed - start drag operation */
928+
if (side_pressed && !android->stylus_side_button_active)
929+
{
930+
/* Start new pointer down */
931+
struct video_viewport vp = {0};
932+
933+
video_driver_translate_coord_viewport_confined_wrap(
934+
&vp, x, y,
935+
&android->pointer[motion_ptr].confined_x,
936+
&android->pointer[motion_ptr].confined_y,
937+
&android->pointer[motion_ptr].full_x,
938+
&android->pointer[motion_ptr].full_y);
939+
940+
video_driver_translate_coord_viewport_wrap(
941+
&vp, x, y,
942+
&android->pointer[motion_ptr].x,
943+
&android->pointer[motion_ptr].y,
944+
&android->pointer[motion_ptr].full_x,
945+
&android->pointer[motion_ptr].full_y);
946+
947+
if (android->pointer_count < (int)motion_ptr + 1)
948+
android->pointer_count = (int)motion_ptr + 1;
949+
950+
android->stylus_side_button_active = true;
951+
android->stylus_side_button_ptr = motion_ptr;
952+
953+
#ifdef DEBUG_ANDROID_INPUT
954+
RARCH_LOG("[Stylus] POINTER DOWN @ (%.1f, %.1f) idx=%zu cnt=%d (side button start)\n",
955+
x, y, motion_ptr, android->pointer_count);
956+
#endif
957+
return;
958+
}
959+
/* Side button held - continue drag (update coordinates) */
960+
else if (side_pressed && android->stylus_side_button_active)
961+
{
962+
/* Update existing pointer coordinates */
963+
struct video_viewport vp = {0};
964+
size_t ptr_idx = android->stylus_side_button_ptr;
965+
966+
video_driver_translate_coord_viewport_confined_wrap(
967+
&vp, x, y,
968+
&android->pointer[ptr_idx].confined_x,
969+
&android->pointer[ptr_idx].confined_y,
970+
&android->pointer[ptr_idx].full_x,
971+
&android->pointer[ptr_idx].full_y);
972+
973+
video_driver_translate_coord_viewport_wrap(
974+
&vp, x, y,
975+
&android->pointer[ptr_idx].x,
976+
&android->pointer[ptr_idx].y,
977+
&android->pointer[ptr_idx].full_x,
978+
&android->pointer[ptr_idx].full_y);
979+
980+
#ifdef DEBUG_ANDROID_INPUT
981+
RARCH_LOG("[Stylus] POINTER MOVE @ (%.1f, %.1f) idx=%zu (side button drag)\n",
982+
x, y, ptr_idx);
983+
#endif
984+
return;
985+
}
986+
/* Side button released - end drag operation */
987+
else if (!side_pressed && android->stylus_side_button_active)
988+
{
989+
/* End pointer operation */
990+
size_t ptr_idx = android->stylus_side_button_ptr;
991+
992+
if (ptr_idx < MAX_TOUCH - 1)
993+
{
994+
memmove(android->pointer + ptr_idx,
995+
android->pointer + ptr_idx + 1,
996+
(MAX_TOUCH - ptr_idx - 1) * sizeof(android->pointer[0]));
997+
}
998+
if (android->pointer_count > 0)
999+
android->pointer_count--;
1000+
1001+
android->stylus_side_button_active = false;
1002+
1003+
#ifdef DEBUG_ANDROID_INPUT
1004+
RARCH_LOG("[Stylus] POINTER UP idx=%zu cnt=%d (side button end)\n",
1005+
ptr_idx, android->pointer_count);
1006+
#endif
1007+
return;
1008+
}
1009+
1010+
return; /* Standard hover - no clicks allowed */
8981011

8991012
case AMOTION_EVENT_ACTION_DOWN:
9001013
case AMOTION_EVENT_ACTION_MOVE:
@@ -932,8 +1045,7 @@ static INLINE void android_input_poll_event_type_motion(
9321045
/* Apply contact requirement setting */
9331046
stylus_pressed = require_contact
9341047
? tip_down /* Only tip contact counts when setting enabled */
935-
: (tip_down || side_primary ||
936-
action == AMOTION_EVENT_ACTION_DOWN); /* Tip or side */
1048+
: (tip_down || side_primary); /* Tip contact OR side button when disabled */
9371049

9381050
#ifdef DEBUG_ANDROID_INPUT
9391051
RARCH_LOG("[RA Input] S Pen contact - req_contact:%s tip_down:%s "

0 commit comments

Comments
 (0)