Skip to content

Commit abcd427

Browse files
authored
refactor: rewrite input handling to better support AINPUT_SOURCE_STYLUS (#15597)
Resolves issues with S-Pen on Samsung devices, also adds support for S-Pen button that is handled as r-mouse click now.
1 parent 2d2cb04 commit abcd427

File tree

1 file changed

+89
-4
lines changed

1 file changed

+89
-4
lines changed

input/drivers/android_input.c

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,14 @@ enum {
6161
AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
6262
AMOTION_EVENT_AXIS_VSCROLL = 9,
6363
AMOTION_EVENT_ACTION_HOVER_MOVE = 7,
64-
AINPUT_SOURCE_STYLUS = 0x00004000
64+
AINPUT_SOURCE_STYLUS = 0x00004002,
65+
AMOTION_EVENT_BUTTON_STYLUS_PRIMARY = 1 << 5,
66+
AMOTION_EVENT_BUTTON_STYLUS_SECONDARY = 1 << 6
6567
};
6668
#endif
6769

70+
#define AINPUT_SOURCE_TOUCHSCREEN_OR_MOUSE AINPUT_SOURCE_TOUCHSCREEN|AINPUT_SOURCE_MOUSE
71+
6872
/* If using an SDK lower than 24 then add missing relative axis codes */
6973
#ifndef AMOTION_EVENT_AXIS_RELATIVE_X
7074
#define AMOTION_EVENT_AXIS_RELATIVE_X 27
@@ -818,6 +822,86 @@ static INLINE void android_input_poll_event_type_motion(
818822
android->mouse_r = (android->pointer_count == 2);
819823
}
820824

825+
826+
static INLINE void android_input_poll_event_type_motion_stylus(
827+
android_input_t *android, AInputEvent *event,
828+
int port, int source)
829+
{
830+
int getaction = AMotionEvent_getAction(event);
831+
int action = getaction & AMOTION_EVENT_ACTION_MASK;
832+
size_t motion_ptr = getaction >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
833+
834+
if (ENABLE_TOUCH_SCREEN_MOUSE)
835+
{
836+
// mouse right button press on stylus primary button
837+
int btn = (int)AMotionEvent_getButtonState(event);
838+
android->mouse_r = (btn & AMOTION_EVENT_BUTTON_STYLUS_PRIMARY);
839+
}
840+
841+
bool hovered_or_moving = (
842+
action == AMOTION_EVENT_ACTION_HOVER_MOVE
843+
|| action == AMOTION_EVENT_ACTION_MOVE);
844+
845+
if (hovered_or_moving && motion_ptr < MAX_TOUCH)
846+
{
847+
if (ENABLE_TOUCH_SCREEN_MOUSE)
848+
{
849+
if (action == AMOTION_EVENT_ACTION_MOVE) {
850+
android->mouse_l = 1;
851+
} else {
852+
android->mouse_l = 0;
853+
}
854+
855+
android_mouse_calculate_deltas(android,event,motion_ptr);
856+
}
857+
858+
if (action == AMOTION_EVENT_ACTION_MOVE) {
859+
// move pointer
860+
861+
struct video_viewport vp;
862+
float x = AMotionEvent_getX(event, motion_ptr);
863+
float y = AMotionEvent_getY(event, motion_ptr);
864+
865+
vp.x = 0;
866+
vp.y = 0;
867+
vp.width = 0;
868+
vp.height = 0;
869+
vp.full_width = 0;
870+
vp.full_height = 0;
871+
872+
video_driver_translate_coord_viewport_wrap(
873+
&vp,
874+
x, y,
875+
&android->pointer[motion_ptr].x,
876+
&android->pointer[motion_ptr].y,
877+
&android->pointer[motion_ptr].full_x,
878+
&android->pointer[motion_ptr].full_y);
879+
880+
android->pointer_count = MAX(
881+
android->pointer_count,
882+
motion_ptr + 1);
883+
} else if (action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
884+
// release the pointer
885+
886+
memmove(android->pointer + motion_ptr,
887+
android->pointer + motion_ptr + 1,
888+
(MAX_TOUCH - motion_ptr - 1) * sizeof(struct input_pointer));
889+
890+
if (android->pointer_count > 0)
891+
android->pointer_count--;
892+
}
893+
} else if ((action == AMOTION_EVENT_ACTION_HOVER_EXIT) && motion_ptr < MAX_TOUCH) {
894+
if (ENABLE_TOUCH_SCREEN_MOUSE)
895+
{
896+
android->mouse_l = 0;
897+
898+
android_mouse_calculate_deltas(android,event,motion_ptr);
899+
}
900+
901+
// pointer was already released during AMOTION_EVENT_ACTION_HOVER_MOVE
902+
}
903+
}
904+
821905
static bool android_is_keyboard_id(int id)
822906
{
823907
unsigned i;
@@ -1477,9 +1561,10 @@ static void android_input_poll_input_default(android_input_t *android)
14771561
case AINPUT_EVENT_TYPE_MOTION:
14781562
if ((source & AINPUT_SOURCE_TOUCHPAD))
14791563
engine_handle_touchpad(android_app, event, port);
1480-
/* Only handle events from a touchscreen or mouse */
1481-
else if ((source & (AINPUT_SOURCE_TOUCHSCREEN
1482-
| AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE)))
1564+
else if ((source & AINPUT_SOURCE_STYLUS) == AINPUT_SOURCE_STYLUS)
1565+
android_input_poll_event_type_motion_stylus(android, event,
1566+
port, source);
1567+
else if ((source & AINPUT_SOURCE_TOUCHSCREEN_OR_MOUSE) == AINPUT_SOURCE_TOUCHSCREEN_OR_MOUSE)
14831568
android_input_poll_event_type_motion(android, event,
14841569
port, source);
14851570
else

0 commit comments

Comments
 (0)