diff --git a/input/drivers/android_input.c b/input/drivers/android_input.c index 8e4f16ae9e..eaa286afc7 100644 --- a/input/drivers/android_input.c +++ b/input/drivers/android_input.c @@ -115,6 +115,7 @@ typedef struct struct input_pointer { int16_t x, y; + int16_t confined_x, confined_y; int16_t full_x, full_y; }; @@ -818,16 +819,20 @@ static INLINE void android_input_poll_event_type_motion( for (motion_ptr = 0; motion_ptr < pointer_max; motion_ptr++) { - struct video_viewport vp; + struct video_viewport vp = {0}; float x = AMotionEvent_getX(event, motion_ptr); float y = AMotionEvent_getY(event, motion_ptr); - vp.x = 0; - vp.y = 0; - vp.width = 0; - vp.height = 0; - vp.full_width = 0; - vp.full_height = 0; + /* On other platforms, pointer query uses the confined wrap function, * + * but some extra functionality is added to Android which needs the * + * true offscreen value -0x8000, so both variants are called. */ + video_driver_translate_coord_viewport_confined_wrap( + &vp, + x, y, + &android->pointer[motion_ptr].confined_x, + &android->pointer[motion_ptr].confined_y, + &android->pointer[motion_ptr].full_x, + &android->pointer[motion_ptr].full_y); video_driver_translate_coord_viewport_wrap( &vp, @@ -1733,10 +1738,8 @@ static int16_t android_input_state( case RETRO_DEVICE_MOUSE: case RARCH_DEVICE_MOUSE_SCREEN: { + /* Same mouse state is reported for all ports. */ int val = 0; - if (port > 0) - break; /* TODO: implement mouse for additional ports/players */ - switch (id) { case RETRO_DEVICE_ID_MOUSE_LEFT: @@ -1774,11 +1777,15 @@ static int16_t android_input_state( break; case RETRO_DEVICE_LIGHTGUN: { + /* Same lightgun state is reported for all ports. */ int val = 0; - if (port > 0) - break; /* TODO: implement lightgun for additional ports/players */ switch (id) { + case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X: + return android->pointer[idx].x; + case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y: + return android->pointer[idx].y; + /* Deprecated relative lightgun. */ case RETRO_DEVICE_ID_LIGHTGUN_X: val = android->mouse_x_delta; android->mouse_x_delta = 0; @@ -1789,32 +1796,36 @@ static int16_t android_input_state( android->mouse_y_delta = 0; /* flush delta after it has been read */ return val; - case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER: - return android->mouse_l || android_check_quick_tap(android); case RETRO_DEVICE_ID_LIGHTGUN_CURSOR: - return android->mouse_m; - case RETRO_DEVICE_ID_LIGHTGUN_TURBO: - return android->mouse_r; + case RETRO_DEVICE_ID_LIGHTGUN_RELOAD: + return android->mouse_m || android->pointer_count == 3; + case RETRO_DEVICE_ID_LIGHTGUN_SELECT: + return android->mouse_r && android->mouse_l; case RETRO_DEVICE_ID_LIGHTGUN_START: - return android->mouse_m && android->mouse_r; - case RETRO_DEVICE_ID_LIGHTGUN_PAUSE: - return android->mouse_m && android->mouse_l; + case RETRO_DEVICE_ID_LIGHTGUN_TURBO: + return android->mouse_r || android->pointer_count == 2; + case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER: + return android->mouse_l || android_check_quick_tap(android) || android->pointer_count == 1; + case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN: + return input_driver_pointer_is_offscreen(android->pointer[idx].x, android->pointer[idx].y); } } break; case RETRO_DEVICE_POINTER: case RARCH_DEVICE_POINTER_SCREEN: + /* Same pointer state is reported for all ports. */ switch (id) { case RETRO_DEVICE_ID_POINTER_X: if (device == RARCH_DEVICE_POINTER_SCREEN) return android->pointer[idx].full_x; - return android->pointer[idx].x; + return android->pointer[idx].confined_x; case RETRO_DEVICE_ID_POINTER_Y: if (device == RARCH_DEVICE_POINTER_SCREEN) return android->pointer[idx].full_y; - return android->pointer[idx].y; + return android->pointer[idx].confined_y; case RETRO_DEVICE_ID_POINTER_PRESSED: + /* On mobile platforms, touches outside screen / core viewport are not reported. */ if (device == RARCH_DEVICE_POINTER_SCREEN) return (idx < android->pointer_count) && (android->pointer[idx].full_x != -0x8000) && @@ -1822,6 +1833,8 @@ static int16_t android_input_state( return (idx < android->pointer_count) && (android->pointer[idx].x != -0x8000) && (android->pointer[idx].y != -0x8000); + case RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN: + return input_driver_pointer_is_offscreen(android->pointer[idx].x, android->pointer[idx].y); case RETRO_DEVICE_ID_POINTER_COUNT: return android->pointer_count; case RARCH_DEVICE_ID_POINTER_BACK: diff --git a/input/drivers/udev_input.c b/input/drivers/udev_input.c index cc3981b1b3..01834f133e 100644 --- a/input/drivers/udev_input.c +++ b/input/drivers/udev_input.c @@ -3685,7 +3685,7 @@ static bool udev_mouse_button_pressed( } static int16_t udev_pointer_state(udev_input_t *udev, - unsigned port, unsigned id, bool screen) + unsigned port, unsigned idx, unsigned id, bool screen) { udev_input_mouse_t *mouse = udev_get_mouse(udev, port); int16_t res_x; @@ -3701,8 +3701,19 @@ static int16_t udev_pointer_state(udev_input_t *udev, return res_y; case RETRO_DEVICE_ID_POINTER_PRESSED: if (mouse->abs == 1) - return mouse->pp; - return mouse->l; + { + if (idx == 0) + return mouse->pp; + else + return 0; + } + /* Simulate max. 3 touches with mouse buttons*/ + else if (idx == 0) + return (mouse->l | mouse->r | mouse->m); + else if (idx == 1) + return (mouse->r | mouse->m); + else if (idx == 2) + return mouse->m; case RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN: return input_driver_pointer_is_offscreen(res_x, res_y); } @@ -3828,8 +3839,8 @@ static int16_t udev_input_state( return udev_input_touch_state(udev, pointer_dev, binds, keyboard_mapping_blocked, port, device, idx, id); #endif - if (idx == 0) /* multi-touch unsupported (for now) */ - return udev_pointer_state(udev, port, id, + if (idx < 3) + return udev_pointer_state(udev, port, idx, id, device == RARCH_DEVICE_POINTER_SCREEN); break; diff --git a/input/drivers/wayland_input.c b/input/drivers/wayland_input.c index 56c8e4096c..f1c86ef455 100644 --- a/input/drivers/wayland_input.c +++ b/input/drivers/wayland_input.c @@ -109,18 +109,16 @@ static int16_t input_wl_touch_state(input_ctx_wayland_data_t *wl, { if (idx <= MAX_TOUCHES) { - struct video_viewport vp; + struct video_viewport vp = {0}; int16_t res_x = 0; int16_t res_y = 0; int16_t res_screen_x = 0; int16_t res_screen_y = 0; - vp.x = 0; - vp.y = 0; - vp.width = 0; - vp.height = 0; - vp.full_width = 0; - vp.full_height = 0; + /* Shortcut: mouse button events will be reported on desktop with 0/0 coordinates. * + * Skip these, mouse handling will catch it elsewhere. */ + if (wl->touches[idx].x == 0 && wl->touches[idx].y == 0) + return 0; if (video_driver_translate_coord_viewport_confined_wrap(&vp, wl->touches[idx].x, wl->touches[idx].y, @@ -132,17 +130,14 @@ static int16_t input_wl_touch_state(input_ctx_wayland_data_t *wl, res_y = res_screen_y; } - if ((res_x >= -0x7fff) && (res_y >= -0x7fff)) /* Inside? */ + switch (id) { - switch (id) - { - case RETRO_DEVICE_ID_POINTER_X: - return res_x; - case RETRO_DEVICE_ID_POINTER_Y: - return res_y; - case RETRO_DEVICE_ID_POINTER_PRESSED: - return wl->touches[idx].active; - } + case RETRO_DEVICE_ID_POINTER_X: + return res_x; + case RETRO_DEVICE_ID_POINTER_Y: + return res_y; + case RETRO_DEVICE_ID_POINTER_PRESSED: + return wl->touches[idx].active; } } } @@ -301,8 +296,18 @@ static int16_t input_wl_state( } break; case RETRO_DEVICE_POINTER: + case RARCH_DEVICE_POINTER_SCREEN: /* All ports report the same pointer state. See notes at mouse case. */ - if (idx == 0) + if (idx < MAX_TOUCHES) + { + int16_t touch_state = input_wl_touch_state(wl, idx, id, + device == RARCH_DEVICE_POINTER_SCREEN); + /* Touch state is only reported if it is meaningful. */ + if (touch_state) + return touch_state; + } + /* Fall through to system pointer emulating max. 3 touches. */ + if (idx < 3) { struct video_viewport vp = {0}; bool screen = @@ -329,7 +334,12 @@ static int16_t input_wl_state( case RETRO_DEVICE_ID_POINTER_Y: return res_y; case RETRO_DEVICE_ID_POINTER_PRESSED: - return wl->mouse.left; + if (idx == 0) + return (wl->mouse.left | wl->mouse.right | wl->mouse.middle); + else if (idx == 1) + return (wl->mouse.right | wl->mouse.middle); + else if (idx == 2) + return wl->mouse.middle; case RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN: return input_driver_pointer_is_offscreen(res_x, res_y); default: @@ -338,14 +348,6 @@ static int16_t input_wl_state( } } break; - case RARCH_DEVICE_POINTER_SCREEN: - if (port == 0) /* TODO/FIXME: support pointers on additional ports */ - { - if (idx < MAX_TOUCHES) - return input_wl_touch_state(wl, idx, id, - device == RARCH_DEVICE_POINTER_SCREEN); - } - break; case RETRO_DEVICE_LIGHTGUN: /* All ports report the same lightgun state. See notes at mouse case. */ { diff --git a/input/drivers/x11_input.c b/input/drivers/x11_input.c index cbfa6b5d33..23a7e4d8de 100644 --- a/input/drivers/x11_input.c +++ b/input/drivers/x11_input.c @@ -241,7 +241,8 @@ static int16_t x_input_state( break; case RETRO_DEVICE_POINTER: case RARCH_DEVICE_POINTER_SCREEN: - if (idx == 0) + /* Map up to 3 touches to mouse buttons. */ + if (idx < 3) { struct video_viewport vp = {0}; bool screen = @@ -268,7 +269,12 @@ static int16_t x_input_state( case RETRO_DEVICE_ID_POINTER_Y: return res_y; case RETRO_DEVICE_ID_POINTER_PRESSED: - return x11->mouse_l; + if (idx == 0) + return (x11->mouse_l | x11->mouse_r | x11->mouse_m); + else if (idx == 1) + return (x11->mouse_r | x11->mouse_m); + else if (idx == 2) + return x11->mouse_m; case RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN: return input_driver_pointer_is_offscreen(res_x, res_y); } diff --git a/input/input_driver.c b/input/input_driver.c index 0a5b1e7c3f..49fc73f19a 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -1207,64 +1207,36 @@ static int16_t input_overlay_lightgun_state(settings_t *settings, switch(id) { + /* Pointer positions have been clamped earlier in input drivers, * + * so if we want to pass true offscreen value, it must be detected */ case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X: ptr_st->device_mask |= (1 << RETRO_DEVICE_LIGHTGUN); - - if ( ptr_st->ptr[0].x != -0x8000 - || settings->bools.input_overlay_lightgun_allow_offscreen) + if ( ( ptr_st->ptr[0].x > -0x7fff && ptr_st->ptr[0].x != 0x7fff) + || !settings->bools.input_overlay_lightgun_allow_offscreen) return ptr_st->ptr[0].x; - else if (video_driver_get_viewport_info(&vp)) - { - edge = ((2 * vp.x * 0x7fff) / (int)vp.full_width) - 0x7fff; - return ((ptr_st->screen_x > edge) ? 0x7fff : -0x7fff); - } - return -0x8000; + else + return -0x8000; case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y: - if ( ptr_st->ptr[0].y != -0x8000 - || settings->bools.input_overlay_lightgun_allow_offscreen) + if ( ( ptr_st->ptr[0].y > -0x7fff && ptr_st->ptr[0].y != 0x7fff) + || !settings->bools.input_overlay_lightgun_allow_offscreen) return ptr_st->ptr[0].y; - else if (video_driver_get_viewport_info(&vp)) - { - edge = ((2 * vp.y * 0x7fff) / (int)vp.full_height) - 0x7fff; - return ((ptr_st->screen_y > edge) ? 0x7fff : -0x7fff); - } - return -0x8000; + else + return -0x8000; case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN: - return ( settings->bools.input_overlay_lightgun_allow_offscreen - && (ptr_st->ptr[0].x == -0x8000 || ptr_st->ptr[0].y == -0x8000)); + return input_driver_pointer_is_offscreen(ptr_st->ptr[0].x, ptr_st->ptr[0].y); case RETRO_DEVICE_ID_LIGHTGUN_AUX_A: - rarch_id = RARCH_LIGHTGUN_AUX_A; - break; case RETRO_DEVICE_ID_LIGHTGUN_AUX_B: - rarch_id = RARCH_LIGHTGUN_AUX_B; - break; case RETRO_DEVICE_ID_LIGHTGUN_AUX_C: - rarch_id = RARCH_LIGHTGUN_AUX_C; - break; case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER: - rarch_id = RARCH_LIGHTGUN_TRIGGER; - break; case RETRO_DEVICE_ID_LIGHTGUN_START: case RETRO_DEVICE_ID_LIGHTGUN_PAUSE: - rarch_id = RARCH_LIGHTGUN_START; - break; case RETRO_DEVICE_ID_LIGHTGUN_SELECT: - rarch_id = RARCH_LIGHTGUN_SELECT; - break; case RETRO_DEVICE_ID_LIGHTGUN_RELOAD: - rarch_id = RARCH_LIGHTGUN_RELOAD; - break; case RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP: - rarch_id = RARCH_LIGHTGUN_DPAD_UP; - break; case RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN: - rarch_id = RARCH_LIGHTGUN_DPAD_DOWN; - break; case RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT: - rarch_id = RARCH_LIGHTGUN_DPAD_LEFT; - break; case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT: - rarch_id = RARCH_LIGHTGUN_DPAD_RIGHT; + rarch_id = input_driver_lightgun_id_convert(id); break; default: rarch_id = RARCH_BIND_LIST_END; @@ -1294,6 +1266,8 @@ static int16_t input_overlay_pointer_state(input_overlay_t *ol, && ptr_st->ptr[idx].y != -0x8000; case RETRO_DEVICE_ID_POINTER_COUNT: return ptr_st->count; + case RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN: + return input_driver_pointer_is_offscreen(ptr_st->ptr[idx].x, ptr_st->ptr[idx].y); } return 0;