[UWP] Mouse fix on high DPI, multi touch support

This commit is contained in:
driver1998 2019-12-05 15:51:12 +08:00 committed by GH Cao
parent 1bd9d503f0
commit 004d782323

View File

@ -166,6 +166,14 @@ const struct rarch_key_map rarch_key_map_uwp[] = {
{ 0, RETROK_UNKNOWN }
};
#define MAX_TOUCH 16
struct input_pointer {
int id;
bool isInContact;
short x, y;
short full_x, full_y;
};
struct uwp_input_state_t {
short mouse_screen_x;
short mouse_screen_y;
@ -178,15 +186,20 @@ struct uwp_input_state_t {
bool mouse_button5;
short mouse_wheel_left;
short mouse_wheel_up;
short touch_screen_x;
short touch_screen_y;
short touch_rel_x;
short touch_rel_y;
bool touch_touched;
unsigned touch_count;
struct input_pointer touch[MAX_TOUCH];
};
struct uwp_input_state_t uwp_current_input, uwp_next_input;
// Taken from DirectX UWP samples - on Xbox, everything is scaled 200% so getting the DPI calculation correct is crucial
static inline float ConvertDipsToPixels(float dips, float dpi)
{
static const float dipsPerInch = 96.0f;
return floorf(dips * dpi / dipsPerInch + 0.5f);
}
// The main function is only used to initialize our IFrameworkView class.
[Platform::MTAThread]
int main(Platform::Array<Platform::String^>^)
@ -421,6 +434,9 @@ void App::OnKey(CoreWindow^ sender, KeyEventArgs^ args)
void App::OnPointer(CoreWindow^ sender, PointerEventArgs^ args)
{
float dpi = DisplayInformation::GetForCurrentView()->LogicalDpi;
if (args->CurrentPoint->PointerDevice->PointerDeviceType == PointerDeviceType::Mouse)
{
uwp_next_input.mouse_left = args->CurrentPoint->Properties->IsLeftButtonPressed;
@ -428,8 +444,8 @@ void App::OnPointer(CoreWindow^ sender, PointerEventArgs^ args)
uwp_next_input.mouse_right = args->CurrentPoint->Properties->IsRightButtonPressed;
uwp_next_input.mouse_button4 = args->CurrentPoint->Properties->IsXButton1Pressed;
uwp_next_input.mouse_button5 = args->CurrentPoint->Properties->IsXButton2Pressed;
uwp_next_input.mouse_screen_x = args->CurrentPoint->Position.X;
uwp_next_input.mouse_screen_y = args->CurrentPoint->Position.Y;
uwp_next_input.mouse_screen_x = ConvertDipsToPixels(args->CurrentPoint->Position.X, dpi);
uwp_next_input.mouse_screen_y = ConvertDipsToPixels(args->CurrentPoint->Position.Y, dpi);
uwp_next_input.mouse_rel_x = uwp_next_input.mouse_screen_x - uwp_current_input.mouse_screen_x;
uwp_next_input.mouse_rel_y = uwp_next_input.mouse_screen_y - uwp_current_input.mouse_screen_y;
if (args->CurrentPoint->Properties->IsHorizontalMouseWheel)
@ -439,11 +455,53 @@ void App::OnPointer(CoreWindow^ sender, PointerEventArgs^ args)
}
else
{
uwp_next_input.touch_touched = args->CurrentPoint->IsInContact;
uwp_next_input.touch_screen_x = args->CurrentPoint->Position.X;
uwp_next_input.touch_screen_y = args->CurrentPoint->Position.Y;
uwp_next_input.touch_rel_x = uwp_next_input.touch_screen_x - uwp_current_input.touch_screen_x;
uwp_next_input.touch_rel_y = uwp_next_input.touch_screen_y - uwp_current_input.touch_screen_y;
unsigned i, free_index = MAX_TOUCH; bool found = false;
int id = args->CurrentPoint->PointerId;
for (i = 0; i < uwp_next_input.touch_count; i++)
{
if (!uwp_next_input.touch[i].isInContact && free_index == MAX_TOUCH)
free_index = i;
if (uwp_next_input.touch[i].id == id)
{
found = true;
break;
}
}
if (!found)
{
if (free_index >= 0 && free_index < uwp_next_input.touch_count)
i = free_index;
else if (uwp_next_input.touch_count + 1 < MAX_TOUCH)
i = ++uwp_next_input.touch_count;
else
return;
}
uwp_next_input.touch[i].id = id;
struct video_viewport vp;
/* convert from event coordinates to core and screen coordinates */
vp.x = 0;
vp.y = 0;
vp.width = 0;
vp.height = 0;
vp.full_width = 0;
vp.full_height = 0;
video_driver_translate_coord_viewport_wrap(
&vp,
ConvertDipsToPixels(args->CurrentPoint->Position.X, dpi),
ConvertDipsToPixels(args->CurrentPoint->Position.Y, dpi),
&uwp_next_input.touch[i].x,
&uwp_next_input.touch[i].y,
&uwp_next_input.touch[i].full_x,
&uwp_next_input.touch[i].full_y);
uwp_next_input.touch[i].isInContact = args->CurrentPoint->IsInContact;
}
}
@ -480,13 +538,6 @@ void App::OnPackageInstalling(PackageCatalog^ sender, PackageInstallingEventArgs
}
}
// Taken from DirectX UWP samples - on Xbox, everything is scaled 200% so getting the DPI calculation correct is crucial
static inline float ConvertDipsToPixels(float dips, float dpi)
{
static const float dipsPerInch = 96.0f;
return floorf(dips * dpi / dipsPerInch + 0.5f);
}
// Implement UWP equivalents of various win32_* functions
extern "C" {
@ -566,8 +617,6 @@ extern "C" {
uwp_next_input.mouse_rel_y = 0;
uwp_next_input.mouse_wheel_up %= WHEEL_DELTA;
uwp_next_input.mouse_wheel_left %= WHEEL_DELTA;
uwp_next_input.touch_rel_x = 0;
uwp_next_input.touch_rel_y = 0;
}
bool uwp_keyboard_pressed(unsigned key)
@ -616,17 +665,18 @@ extern "C" {
return 0;
}
// TODO: I don't have any touch-enabled Windows devices to test if this actually works
int16_t uwp_pointer_state(unsigned idx, unsigned id, bool screen)
{
switch (id)
{
case RETRO_DEVICE_ID_POINTER_X:
return screen ? uwp_current_input.touch_screen_x : uwp_current_input.touch_rel_x;
return screen ? uwp_current_input.touch[idx].full_x : uwp_current_input.touch[idx].x;
case RETRO_DEVICE_ID_POINTER_Y:
return screen ? uwp_current_input.touch_screen_y : uwp_current_input.touch_rel_y;
return screen ? uwp_current_input.touch[idx].full_y : uwp_current_input.touch[idx].y;
case RETRO_DEVICE_ID_POINTER_PRESSED:
return uwp_current_input.touch_touched;
return uwp_current_input.touch[idx].isInContact;
case RETRO_DEVICE_ID_POINTER_COUNT:
return uwp_current_input.touch_count;
default:
break;
}