diff --git a/gfx/video_driver.c b/gfx/video_driver.c index ad1ce4424b3f..5600e3f3af7e 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -711,20 +711,34 @@ bool video_driver_translate_coord_viewport( || (norm_full_vp_height <= 0)) return false; - if (mouse_x >= 0 && mouse_x < norm_full_vp_width) - scaled_screen_x = ((mouse_x * 0x10000) - / norm_full_vp_width) - 0x7fff; - - if (mouse_y >= 0 && mouse_y < norm_full_vp_height) - scaled_screen_y = ((mouse_y * 0x10000) - / norm_full_vp_height) - 0x7fff; + /* The conditions may look a bit unnecessarily complex, * + * but there are following edge cases to consider: * + * - 0 should map to -0x7fff (not -0x8000) * + * - edge (vp_width -1) should map to 0x7fff * + * This should make it possible to hit the edges on all * + * screen resolutions, even when pointer cannot be * + * moved offscreen. */ + + if (mouse_x > 0 && mouse_x < norm_full_vp_width) + scaled_screen_x = ((mouse_x * 0xffff) + / (norm_full_vp_width - 1)) - 0x8000; + else if (mouse_x == 0) + scaled_screen_x = -0x7fff; + + if (mouse_y > 0 && mouse_y < norm_full_vp_height) + scaled_screen_y = ((mouse_y * 0xffff) + / (norm_full_vp_height - 1)) - 0x8000; + else if (mouse_y == 0) + scaled_screen_y = -0x7fff; mouse_x -= vp->x; mouse_y -= vp->y; - if (mouse_x >= 0 && mouse_x < norm_vp_width) - scaled_x = ((mouse_x * 0x10000) - / norm_vp_width) - 0x7fff; + if (mouse_x > 0 && mouse_x < norm_vp_width) + scaled_x = ((mouse_x * 0xffff) + / (norm_vp_width - 1)) - 0x8000; + else if (mouse_x == 0) + scaled_x = -0x7fff; else if (!report_oob) { if (mouse_x < 0) @@ -733,9 +747,11 @@ bool video_driver_translate_coord_viewport( scaled_x = 0x7fff; } - if (mouse_y >= 0 && mouse_y < norm_vp_height) - scaled_y = ((mouse_y * 0x10000) - / norm_vp_height) - 0x7fff; + if (mouse_y > 0 && mouse_y < norm_vp_height) + scaled_y = ((mouse_y * 0xffff) + / (norm_vp_height - 1)) - 0x8000; + else if (mouse_y == 0) + scaled_y = -0x7fff; else if (!report_oob) { if (mouse_y < 0) diff --git a/input/drivers/udev_input.c b/input/drivers/udev_input.c index ede485ebf874..cc3981b1b3bb 100644 --- a/input/drivers/udev_input.c +++ b/input/drivers/udev_input.c @@ -781,96 +781,60 @@ static int16_t udev_mouse_get_y(const udev_input_mouse_t *mouse) return y + (y < 0 ? -0.5 : 0.5); } -static int16_t udev_mouse_get_pointer_x(const udev_input_mouse_t *mouse, bool screen) +static bool udev_mouse_get_pointer(const udev_input_mouse_t *mouse, + bool screen, bool confined, int16_t *ret_x, int16_t *ret_y) { - video_viewport_t vp; - double src_min; - double src_width; - int32_t x; + struct video_viewport vp = {0}; + int16_t scaled_x; + int16_t scaled_y; + int16_t res_x = 0; + int16_t res_y = 0; + int16_t res_screen_x = 0; + int16_t res_screen_y = 0; if (!video_driver_get_viewport_info(&vp)) - return 0; + return false; /* mouse coords are absolute? */ if (mouse->abs) { - /* mouse coordinates are relative to the screen; convert them + /* mouse coordinates are relative to the full screen; convert them * to be relative to the viewport */ - double scaled_x; - src_min = mouse->x_min; - src_width = mouse->x_max - mouse->x_min + 1; - scaled_x = vp.full_width * (mouse->x_abs - src_min) / src_width; - x = -32767.0 + 65535.0 / vp.width * (scaled_x - vp.x); + scaled_x = mouse->x_abs - mouse->x_min; + scaled_y = mouse->y_abs - mouse->y_min; } else /* mouse coords are viewport relative */ { - if (screen) - { - src_min = 0.0; - src_width = vp.full_width; - } - else - { - src_min = vp.x; - src_width = vp.width; - } - x = -32767.0 + 65535.0 / src_width * (mouse->x_abs - src_min); + scaled_x = mouse->x_abs; + scaled_y = mouse->y_abs; } - x += (x < 0 ? -0.5 : 0.5); - - if (x < -0x7fff) - return -0x7fff; - else if (x > 0x7fff) - return 0x7fff; - - return x; -} - -static int16_t udev_mouse_get_pointer_y(const udev_input_mouse_t *mouse, bool screen) -{ - video_viewport_t vp; - double src_min; - double src_height; - int32_t y; - - if (!video_driver_get_viewport_info(&vp)) - return 0; - - /* Mouse coords are absolute? */ - if (mouse->abs) + if (confined && video_driver_translate_coord_viewport_confined_wrap( + &vp, scaled_x, scaled_y, + &res_x, &res_y, &res_screen_x, &res_screen_y)) { - double scaled_y; - /* mouse coordinates are relative to the screen; convert them - * to be relative to the viewport */ - src_min = mouse->y_min; - src_height = mouse->y_max - mouse->y_min + 1; - scaled_y = vp.full_height * (mouse->y_abs - src_min) / src_height; - y = -32767.0 + 65535.0 / vp.height * (scaled_y - vp.y); } - else /* mouse coords are viewport relative */ + else if (!confined && video_driver_translate_coord_viewport_wrap( + &vp, scaled_x, scaled_y, + &res_x, &res_y, &res_screen_x, &res_screen_y)) { - if (screen) - { - src_min = 0.0; - src_height = vp.full_height; - } - else - { - src_min = vp.y; - src_height = vp.height; - } - y = -32767.0 + 65535.0 / src_height * (mouse->y_abs - src_min); } - - y += (y < 0 ? -0.5 : 0.5); - - if (y < -0x7fff) - return -0x7fff; - else if (y > 0x7fff) - return 0x7fff; - - return y; + else + { + return false; + } + + if (screen) + { + *ret_x = res_screen_x; + *ret_y = res_screen_y; + } + else + { + *ret_x = res_x; + *ret_y = res_y; + } + return true; } static void udev_handle_mouse(void *data, @@ -3616,15 +3580,12 @@ static int16_t udev_lightgun_aiming_state( udev_input_t *udev, unsigned port, unsigned id ) { - const int edge_detect = 32700; udev_input_mouse_t *mouse = udev_get_mouse(udev, port); + int16_t res_x; + int16_t res_y; - if (mouse) + if (mouse && udev_mouse_get_pointer(mouse, false, false, &res_x, &res_y)) { - bool inside = false; - int16_t res_x = udev_mouse_get_pointer_x(mouse, false); - int16_t res_y = udev_mouse_get_pointer_y(mouse, false); - switch ( id ) { case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X: @@ -3632,11 +3593,7 @@ static int16_t udev_lightgun_aiming_state( case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y: return res_y; case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN: - inside = (res_x >= -edge_detect) - && (res_y >= -edge_detect) - && (res_x <= edge_detect) - && (res_y <= edge_detect); - return !inside; + return input_driver_pointer_is_offscreen(res_x, res_y); default: break; } @@ -3731,60 +3688,29 @@ static int16_t udev_pointer_state(udev_input_t *udev, unsigned port, unsigned id, bool screen) { udev_input_mouse_t *mouse = udev_get_mouse(udev, port); + int16_t res_x; + int16_t res_y; - if (mouse) + if (mouse && udev_mouse_get_pointer(mouse, screen, true, &res_x, &res_y)) { switch (id) { case RETRO_DEVICE_ID_POINTER_X: - return udev_mouse_get_pointer_x(mouse, screen); + return res_x; case RETRO_DEVICE_ID_POINTER_Y: - return udev_mouse_get_pointer_y(mouse, screen); + return res_y; case RETRO_DEVICE_ID_POINTER_PRESSED: if (mouse->abs == 1) return mouse->pp; return mouse->l; + case RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN: + return input_driver_pointer_is_offscreen(res_x, res_y); } } return 0; } -static unsigned udev_retro_id_to_rarch(unsigned id) -{ - switch (id) - { - case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT: - return RARCH_LIGHTGUN_DPAD_RIGHT; - case RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT: - return RARCH_LIGHTGUN_DPAD_LEFT; - case RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP: - return RARCH_LIGHTGUN_DPAD_UP; - case RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN: - return RARCH_LIGHTGUN_DPAD_DOWN; - case RETRO_DEVICE_ID_LIGHTGUN_SELECT: - return RARCH_LIGHTGUN_SELECT; - case RETRO_DEVICE_ID_LIGHTGUN_PAUSE: - return RARCH_LIGHTGUN_START; - case RETRO_DEVICE_ID_LIGHTGUN_RELOAD: - return RARCH_LIGHTGUN_RELOAD; - case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER: - return RARCH_LIGHTGUN_TRIGGER; - case RETRO_DEVICE_ID_LIGHTGUN_AUX_A: - return RARCH_LIGHTGUN_AUX_A; - case RETRO_DEVICE_ID_LIGHTGUN_AUX_B: - return RARCH_LIGHTGUN_AUX_B; - case RETRO_DEVICE_ID_LIGHTGUN_AUX_C: - return RARCH_LIGHTGUN_AUX_C; - case RETRO_DEVICE_ID_LIGHTGUN_START: - return RARCH_LIGHTGUN_START; - default: - break; - } - - return 0; -} - static int16_t udev_input_state( void *data, const input_device_driver_t *joypad, @@ -3935,7 +3861,7 @@ static int16_t udev_input_state( case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT: case RETRO_DEVICE_ID_LIGHTGUN_PAUSE: /* deprecated */ { - unsigned new_id = udev_retro_id_to_rarch(id); + unsigned new_id = input_driver_lightgun_id_convert(id); const uint64_t bind_joykey = input_config_binds[port][new_id].joykey; const uint64_t bind_joyaxis = input_config_binds[port][new_id].joyaxis; const uint64_t autobind_joykey = input_autoconf_binds[port][new_id].joykey; diff --git a/input/drivers/x11_input.c b/input/drivers/x11_input.c index 8c6bcad13f3d..cbfa6b5d331b 100644 --- a/input/drivers/x11_input.c +++ b/input/drivers/x11_input.c @@ -103,41 +103,6 @@ static bool x_mouse_button_pressed( return false; } -static unsigned x_retro_id_to_rarch(unsigned id) -{ - switch (id) - { - case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT: - return RARCH_LIGHTGUN_DPAD_RIGHT; - case RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT: - return RARCH_LIGHTGUN_DPAD_LEFT; - case RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP: - return RARCH_LIGHTGUN_DPAD_UP; - case RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN: - return RARCH_LIGHTGUN_DPAD_DOWN; - case RETRO_DEVICE_ID_LIGHTGUN_SELECT: - return RARCH_LIGHTGUN_SELECT; - case RETRO_DEVICE_ID_LIGHTGUN_PAUSE: - return RARCH_LIGHTGUN_START; - case RETRO_DEVICE_ID_LIGHTGUN_RELOAD: - return RARCH_LIGHTGUN_RELOAD; - case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER: - return RARCH_LIGHTGUN_TRIGGER; - case RETRO_DEVICE_ID_LIGHTGUN_AUX_A: - return RARCH_LIGHTGUN_AUX_A; - case RETRO_DEVICE_ID_LIGHTGUN_AUX_B: - return RARCH_LIGHTGUN_AUX_B; - case RETRO_DEVICE_ID_LIGHTGUN_AUX_C: - return RARCH_LIGHTGUN_AUX_C; - case RETRO_DEVICE_ID_LIGHTGUN_START: - return RARCH_LIGHTGUN_START; - default: - break; - } - - return 0; -} - static int16_t x_input_state( void *data, const input_device_driver_t *joypad, @@ -278,22 +243,15 @@ static int16_t x_input_state( case RARCH_DEVICE_POINTER_SCREEN: if (idx == 0) { - struct video_viewport vp; - bool screen = device == RARCH_DEVICE_POINTER_SCREEN; - bool inside = false; + struct video_viewport vp = {0}; + bool screen = + (device == RARCH_DEVICE_POINTER_SCREEN); 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; - - if (video_driver_translate_coord_viewport_wrap( + if (video_driver_translate_coord_viewport_confined_wrap( &vp, x11->mouse_x, x11->mouse_y, &res_x, &res_y, &res_screen_x, &res_screen_y)) { @@ -303,11 +261,6 @@ static int16_t x_input_state( res_y = res_screen_y; } - inside = (res_x >= -0x7fff) && (res_y >= -0x7fff); - - if (!inside) - return 0; - switch (id) { case RETRO_DEVICE_ID_POINTER_X: @@ -316,6 +269,8 @@ static int16_t x_input_state( return res_y; case RETRO_DEVICE_ID_POINTER_PRESSED: return x11->mouse_l; + case RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN: + return input_driver_pointer_is_offscreen(res_x, res_y); } } } @@ -328,42 +283,24 @@ static int16_t x_input_state( case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y: case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN: { - struct video_viewport vp; - const int edge_detect = 32700; - bool inside = false; + 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; - if (video_driver_translate_coord_viewport_wrap(&vp, x11->mouse_x, x11->mouse_y, &res_x, &res_y, &res_screen_x, &res_screen_y)) { - inside = (res_x >= -edge_detect) - && (res_y >= -edge_detect) - && (res_x <= edge_detect) - && (res_y <= edge_detect); - switch ( id ) { case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X: - if (inside) - return res_x; - break; + return res_x; case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y: - if (inside) - return res_y; - break; + return res_y; case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN: - return !inside; + return input_driver_pointer_is_offscreen(res_x, res_y); default: break; } @@ -384,7 +321,7 @@ static int16_t x_input_state( case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT: case RETRO_DEVICE_ID_LIGHTGUN_PAUSE: /* deprecated */ { - unsigned new_id = x_retro_id_to_rarch(id); + unsigned new_id = input_driver_lightgun_id_convert(id); const uint64_t bind_joykey = input_config_binds[port][new_id].joykey; const uint64_t bind_joyaxis = input_config_binds[port][new_id].joyaxis; const uint64_t autobind_joykey = input_autoconf_binds[port][new_id].joykey; @@ -410,11 +347,8 @@ static int16_t x_input_state( && x_keyboard_pressed(x11, binds[port][new_id].key) ) return 1; - else if (settings->uints.input_mouse_index[port] == 0) - { - if (x_mouse_button_pressed(x11, port, binds[port][new_id].mbutton)) + else if (x_mouse_button_pressed(x11, port, binds[port][new_id].mbutton)) return 1; - } } } break; diff --git a/input/input_driver.c b/input/input_driver.c index b8534e633d76..b0f831a449ec 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -655,6 +655,42 @@ bool input_driver_pointer_is_offscreen(int16_t x, int16_t y) return true; } +unsigned input_driver_lightgun_id_convert(unsigned id) +{ + switch (id) + { + case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT: + return RARCH_LIGHTGUN_DPAD_RIGHT; + case RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT: + return RARCH_LIGHTGUN_DPAD_LEFT; + case RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP: + return RARCH_LIGHTGUN_DPAD_UP; + case RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN: + return RARCH_LIGHTGUN_DPAD_DOWN; + case RETRO_DEVICE_ID_LIGHTGUN_SELECT: + return RARCH_LIGHTGUN_SELECT; + case RETRO_DEVICE_ID_LIGHTGUN_PAUSE: + return RARCH_LIGHTGUN_START; + case RETRO_DEVICE_ID_LIGHTGUN_RELOAD: + return RARCH_LIGHTGUN_RELOAD; + case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER: + return RARCH_LIGHTGUN_TRIGGER; + case RETRO_DEVICE_ID_LIGHTGUN_AUX_A: + return RARCH_LIGHTGUN_AUX_A; + case RETRO_DEVICE_ID_LIGHTGUN_AUX_B: + return RARCH_LIGHTGUN_AUX_B; + case RETRO_DEVICE_ID_LIGHTGUN_AUX_C: + return RARCH_LIGHTGUN_AUX_C; + case RETRO_DEVICE_ID_LIGHTGUN_START: + return RARCH_LIGHTGUN_START; + default: + break; + } + + return 0; +} + + bool input_driver_button_combo( unsigned mode, retro_time_t current_time, diff --git a/input/input_driver.h b/input/input_driver.h index 420615bfa9bc..09174b9219eb 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -922,6 +922,8 @@ char *input_config_get_device_name_ptr(unsigned port); */ size_t input_config_get_device_name_size(unsigned port); +unsigned input_driver_lightgun_id_convert(unsigned id); + bool input_driver_pointer_is_offscreen(int16_t x, int16_t y); bool input_driver_button_combo(