@@ -61,11 +61,17 @@ 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 = 0x00004002 ,
64+ AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER ,
6565 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY = 1 << 5 ,
6666 AMOTION_EVENT_BUTTON_STYLUS_SECONDARY = 1 << 6
6767};
6868#endif
69+ /* If using an NDK lower than 16b then add missing definition */
70+ #ifndef __ANDROID_API_O_MR1__
71+ enum {
72+ AINPUT_SOURCE_MOUSE_RELATIVE = 0x00020000 | AINPUT_SOURCE_CLASS_NAVIGATION
73+ };
74+ #endif
6975
7076/* If using an SDK lower than 24 then add missing relative axis codes */
7177#ifndef AMOTION_EVENT_AXIS_RELATIVE_X
@@ -144,6 +150,7 @@ typedef struct android_input
144150{
145151 int64_t quick_tap_time ;
146152 state_device_t pad_states [MAX_USERS ]; /* int alignment */
153+ int mouse_x , mouse_y ;
147154 int mouse_x_delta , mouse_y_delta ;
148155 int mouse_l , mouse_r , mouse_m , mouse_wu , mouse_wd ;
149156 unsigned pads_connected ;
@@ -638,53 +645,77 @@ static int android_check_quick_tap(android_input_t *android)
638645}
639646
640647static INLINE void android_mouse_calculate_deltas (android_input_t * android ,
641- AInputEvent * event ,size_t motion_ptr )
648+ AInputEvent * event ,size_t motion_ptr , int source )
642649{
643- /* Adjust mouse speed based on ratio
644- * between core resolution and system resolution */
645- float x = 0 , y = 0 ;
646- float x_scale = 1 ;
647- float y_scale = 1 ;
648- settings_t * settings = config_get_ptr ();
649- video_driver_state_t * video_st = video_state_get_ptr ();
650- struct retro_system_av_info * av_info = & video_st -> av_info ;
651-
652- if (av_info )
650+ unsigned video_width , video_height ;
651+ video_driver_get_size (& video_width , & video_height );
652+
653+ float x = 0 ;
654+ float x_delta = 0 ;
655+ float x_min = 0 ;
656+ float x_max = (float )video_width ;
657+
658+ float y = 0 ;
659+ float y_delta = 0 ;
660+ float y_min = 0 ;
661+ float y_max = (float )video_height ;
662+
663+ /* AINPUT_SOURCE_MOUSE_RELATIVE is available on Oreo (SDK 26) and newer,
664+ * it passes the relative coordinates in the regular X and Y parts.
665+ * NOTE: AINPUT_SOURCE_* defines have multiple bits set so do full check */
666+ if ((source & AINPUT_SOURCE_MOUSE_RELATIVE ) == AINPUT_SOURCE_MOUSE_RELATIVE )
653667 {
654- video_viewport_t * custom_vp = & settings -> video_viewport_custom ;
655- const struct retro_game_geometry * geom = (const struct retro_game_geometry * )& av_info -> geometry ;
656- x_scale = 2 * (float )geom -> base_width / (float )custom_vp -> width ;
657- y_scale = 2 * (float )geom -> base_height / (float )custom_vp -> height ;
668+ x_delta = AMotionEvent_getX (event , motion_ptr );
669+ y_delta = AMotionEvent_getY (event , motion_ptr );
658670 }
659-
660- /* This axis is only available on Android Nougat and on
661- * Android devices with NVIDIA extensions */
662- if (p_AMotionEvent_getAxisValue )
671+ else
663672 {
664- x = AMotionEvent_getAxisValue (event ,AMOTION_EVENT_AXIS_RELATIVE_X ,
665- motion_ptr );
666- y = AMotionEvent_getAxisValue (event ,AMOTION_EVENT_AXIS_RELATIVE_Y ,
667- motion_ptr );
668- }
673+ /* This axis is only available on Android Nougat or on
674+ * Android devices with NVIDIA extensions */
675+ if (p_AMotionEvent_getAxisValue )
676+ {
677+ x_delta = AMotionEvent_getAxisValue (event ,AMOTION_EVENT_AXIS_RELATIVE_X ,
678+ motion_ptr );
679+ y_delta = AMotionEvent_getAxisValue (event ,AMOTION_EVENT_AXIS_RELATIVE_Y ,
680+ motion_ptr );
681+ }
669682
670- /* If AXIS_RELATIVE had 0 values it might be because we're not
671- * running Android Nougat or on a device
672- * with NVIDIA extension, so re-calculate deltas based on
673- * AXIS_X and AXIS_Y. This has limitations
674- * compared to AXIS_RELATIVE because once the Android mouse cursor
675- * hits the edge of the screen it is
676- * not possible to move the in-game mouse any further in that direction.
677- */
678- if (!x && !y )
679- {
680- x = (AMotionEvent_getX (event , motion_ptr ) - android -> mouse_x_prev );
681- y = (AMotionEvent_getY (event , motion_ptr ) - android -> mouse_y_prev );
682- android -> mouse_x_prev = AMotionEvent_getX (event , motion_ptr );
683- android -> mouse_y_prev = AMotionEvent_getY (event , motion_ptr );
683+ /* If AXIS_RELATIVE had 0 values it might be because we're not
684+ * running Android Nougat or on a device
685+ * with NVIDIA extension, so re-calculate deltas based on
686+ * AXIS_X and AXIS_Y. This has limitations
687+ * compared to AXIS_RELATIVE because once the Android mouse cursor
688+ * hits the edge of the screen it is
689+ * not possible to move the in-game mouse any further in that direction.
690+ */
691+ if (!x_delta && !y_delta )
692+ {
693+ x = AMotionEvent_getX (event , motion_ptr );
694+ y = AMotionEvent_getY (event , motion_ptr );
695+
696+ x_delta = (x_delta - android -> mouse_x_prev );
697+ y_delta = (y_delta - android -> mouse_y_prev );
698+
699+ android -> mouse_x_prev = x ;
700+ android -> mouse_y_prev = y ;
701+ }
684702 }
685703
686- android -> mouse_x_delta = ceil (x ) * x_scale ;
687- android -> mouse_y_delta = ceil (y ) * y_scale ;
704+ android -> mouse_x_delta = x_delta ;
705+ android -> mouse_y_delta = y_delta ;
706+
707+ if (!x ) x = android -> mouse_x + android -> mouse_x_delta ;
708+ if (!y ) y = android -> mouse_y + android -> mouse_y_delta ;
709+
710+ /* x and y are used for the screen mouse, so we want
711+ * to avoid values outside of the viewport resolution */
712+ if (x < x_min ) x = x_min ;
713+ else if (x > x_max ) x = x_max ;
714+ if (y < y_min ) y = y_min ;
715+ else if (y > y_max ) y = y_max ;
716+
717+ android -> mouse_x = x ;
718+ android -> mouse_y = y ;
688719}
689720
690721static INLINE void android_input_poll_event_type_motion (
@@ -697,13 +728,13 @@ static INLINE void android_input_poll_event_type_motion(
697728 bool keyup = (
698729 action == AMOTION_EVENT_ACTION_UP
699730 || action == AMOTION_EVENT_ACTION_CANCEL
700- || action == AMOTION_EVENT_ACTION_POINTER_UP )
701- || (source == AINPUT_SOURCE_MOUSE &&
702- action != AMOTION_EVENT_ACTION_DOWN );
731+ || action == AMOTION_EVENT_ACTION_POINTER_UP );
703732
704733 /* If source is mouse then calculate button state
705- * and mouse deltas and don't process as touchscreen event */
706- if (source == AINPUT_SOURCE_MOUSE )
734+ * and mouse deltas and don't process as touchscreen event.
735+ * NOTE: AINPUT_SOURCE_* defines have multiple bits set so do full check */
736+ if ( (source & AINPUT_SOURCE_MOUSE ) == AINPUT_SOURCE_MOUSE
737+ || (source & AINPUT_SOURCE_MOUSE_RELATIVE ) == AINPUT_SOURCE_MOUSE_RELATIVE )
707738 {
708739 /* getButtonState requires API level 14 */
709740 if (p_AMotionEvent_getButtonState )
@@ -732,7 +763,7 @@ static INLINE void android_input_poll_event_type_motion(
732763 android -> mouse_l = 0 ;
733764 }
734765
735- android_mouse_calculate_deltas (android ,event ,motion_ptr );
766+ android_mouse_calculate_deltas (android ,event ,motion_ptr , source );
736767
737768 return ;
738769 }
@@ -785,7 +816,7 @@ static INLINE void android_input_poll_event_type_motion(
785816 if (( action == AMOTION_EVENT_ACTION_MOVE
786817 || action == AMOTION_EVENT_ACTION_HOVER_MOVE )
787818 && ENABLE_TOUCH_SCREEN_MOUSE )
788- android_mouse_calculate_deltas (android ,event ,motion_ptr );
819+ android_mouse_calculate_deltas (android ,event ,motion_ptr , source );
789820
790821 for (motion_ptr = 0 ; motion_ptr < pointer_max ; motion_ptr ++ )
791822 {
@@ -850,7 +881,7 @@ static INLINE void android_input_poll_event_type_motion_stylus(
850881 android -> mouse_l = 0 ;
851882 }
852883
853- android_mouse_calculate_deltas (android ,event ,motion_ptr );
884+ android_mouse_calculate_deltas (android ,event ,motion_ptr , source );
854885 }
855886
856887 if (action == AMOTION_EVENT_ACTION_MOVE ) {
@@ -893,7 +924,7 @@ static INLINE void android_input_poll_event_type_motion_stylus(
893924 {
894925 android -> mouse_l = 0 ;
895926
896- android_mouse_calculate_deltas (android ,event ,motion_ptr );
927+ android_mouse_calculate_deltas (android ,event ,motion_ptr , source );
897928 }
898929
899930 // pointer was already released during AMOTION_EVENT_ACTION_HOVER_MOVE
@@ -967,7 +998,7 @@ static int android_input_get_id_port(android_input_t *android, int id,
967998 unsigned i ;
968999 int ret = -1 ;
9691000 if (source & (AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_MOUSE |
970- AINPUT_SOURCE_TOUCHPAD ))
1001+ AINPUT_SOURCE_MOUSE_RELATIVE | AINPUT_SOURCE_TOUCHPAD ))
9711002 ret = 0 ; /* touch overlay is always user 1 */
9721003
9731004 for (i = 0 ; i < android -> pads_connected ; i ++ )
@@ -1565,7 +1596,10 @@ static void android_input_poll_input_default(android_input_t *android)
15651596 else if ((source & AINPUT_SOURCE_STYLUS ) == AINPUT_SOURCE_STYLUS )
15661597 android_input_poll_event_type_motion_stylus (android , event ,
15671598 port , source );
1568- else if ((source & (AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_MOUSE )))
1599+ /* Only handle events from a touchscreen or mouse */
1600+ else if ((source & (AINPUT_SOURCE_TOUCHSCREEN
1601+ | AINPUT_SOURCE_MOUSE
1602+ | AINPUT_SOURCE_MOUSE_RELATIVE )))
15691603 android_input_poll_event_type_motion (android , event ,
15701604 port , source );
15711605 else
@@ -1774,6 +1808,7 @@ static int16_t android_input_state(
17741808 case RETRO_DEVICE_KEYBOARD :
17751809 return (id && id < RETROK_LAST ) && BIT_GET (android_key_state [ANDROID_KEYBOARD_PORT ], rarch_keysym_lut [id ]);
17761810 case RETRO_DEVICE_MOUSE :
1811+ case RARCH_DEVICE_MOUSE_SCREEN :
17771812 {
17781813 int val = 0 ;
17791814 if (port > 0 )
@@ -1788,11 +1823,17 @@ static int16_t android_input_state(
17881823 case RETRO_DEVICE_ID_MOUSE_MIDDLE :
17891824 return android -> mouse_m ;
17901825 case RETRO_DEVICE_ID_MOUSE_X :
1826+ if (device == RARCH_DEVICE_MOUSE_SCREEN )
1827+ return android -> mouse_x ;
1828+
17911829 val = android -> mouse_x_delta ;
17921830 android -> mouse_x_delta = 0 ;
17931831 /* flush delta after it has been read */
17941832 return val ;
17951833 case RETRO_DEVICE_ID_MOUSE_Y :
1834+ if (device == RARCH_DEVICE_MOUSE_SCREEN )
1835+ return android -> mouse_y ;
1836+
17961837 val = android -> mouse_y_delta ;
17971838 android -> mouse_y_delta = 0 ;
17981839 /* flush delta after it has been read */
@@ -1907,6 +1948,7 @@ static uint64_t android_input_get_capabilities(void *data)
19071948 return
19081949 (1 << RETRO_DEVICE_JOYPAD )
19091950 | (1 << RETRO_DEVICE_POINTER )
1951+ | (1 << RETRO_DEVICE_MOUSE )
19101952 | (1 << RETRO_DEVICE_KEYBOARD )
19111953 | (1 << RETRO_DEVICE_LIGHTGUN )
19121954 | (1 << RETRO_DEVICE_ANALOG );
@@ -2056,6 +2098,18 @@ static float android_input_get_sensor_input(void *data,
20562098 return 0.0f ;
20572099}
20582100
2101+ static void android_input_grab_mouse (void * data , bool state )
2102+ {
2103+ JNIEnv * env = jni_thread_getenv ();
2104+
2105+ if (!env || !g_android )
2106+ return ;
2107+
2108+ if (g_android -> inputGrabMouse )
2109+ CALL_VOID_METHOD_PARAM (env , g_android -> activity -> clazz ,
2110+ g_android -> inputGrabMouse , state );
2111+ }
2112+
20592113static void android_input_keypress_vibrate ()
20602114{
20612115 static const int keyboard_press = 3 ;
@@ -2077,8 +2131,7 @@ input_driver_t input_android = {
20772131 android_input_get_sensor_input ,
20782132 android_input_get_capabilities ,
20792133 "android" ,
2080-
2081- NULL , /* grab_mouse */
2134+ android_input_grab_mouse ,
20822135 NULL ,
20832136 android_input_keypress_vibrate
20842137};
0 commit comments