SDL: winrt: Fix support for multiple simultaneous mouse button presses

From be5356af932fb9e4db9c97add00e036aeeb6eebf Mon Sep 17 00:00:00 2001
From: Ethan Lee <[EMAIL REDACTED]>
Date: Fri, 14 May 2021 14:44:13 -0400
Subject: [PATCH] winrt: Fix support for multiple simultaneous mouse button
 presses

---
 src/core/winrt/SDL_winrtapp_direct3d.cpp  |  7 ++--
 src/video/winrt/SDL_winrtevents_c.h       |  2 +-
 src/video/winrt/SDL_winrtpointerinput.cpp | 44 ++++++++++++++++-------
 3 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp
index 0018604d1..9c115c6d6 100644
--- a/src/core/winrt/SDL_winrtapp_direct3d.cpp
+++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp
@@ -729,15 +729,18 @@ void SDL_WinRTApp::OnExiting(Platform::Object^ sender, Platform::Object^ args)
 static void
 WINRT_LogPointerEvent(const char * header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint)
 {
+    Uint8 button, pressed;
     Windows::UI::Input::PointerPoint ^ pt = args->CurrentPoint;
-    SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d\n",
+    WINRT_GetSDLButtonForPointerPoint(pt, &button, &pressed);
+    SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d pressed=%d\n",
         header,
         pt->Position.X, pt->Position.Y,
         transformedPoint.X, transformedPoint.Y,
         pt->Properties->MouseWheelDelta,
         pt->FrameId,
         pt->PointerId,
-        WINRT_GetSDLButtonForPointerPoint(pt));
+        button,
+        pressed);
 }
 
 void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
diff --git a/src/video/winrt/SDL_winrtevents_c.h b/src/video/winrt/SDL_winrtevents_c.h
index 910dc6a64..a95e9656a 100644
--- a/src/video/winrt/SDL_winrtevents_c.h
+++ b/src/video/winrt/SDL_winrtevents_c.h
@@ -53,7 +53,7 @@ typedef enum {
 extern Windows::Foundation::Point WINRT_TransformCursorPosition(SDL_Window * window,
                                                                 Windows::Foundation::Point rawPosition,
                                                                 WINRT_CursorNormalizationType normalization);
-extern Uint8 WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt);
+extern SDL_bool WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt, Uint8 *button, Uint8 *pressed);
 extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
 extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
 extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
diff --git a/src/video/winrt/SDL_winrtpointerinput.cpp b/src/video/winrt/SDL_winrtpointerinput.cpp
index 6959be71d..1639083f0 100644
--- a/src/video/winrt/SDL_winrtpointerinput.cpp
+++ b/src/video/winrt/SDL_winrtpointerinput.cpp
@@ -116,8 +116,8 @@ WINRT_TransformCursorPosition(SDL_Window * window,
     return outputPosition;
 }
 
-Uint8
-WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt)
+SDL_bool
+WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt, Uint8 *button, Uint8 *pressed)
 {
     using namespace Windows::UI::Input;
 
@@ -128,30 +128,42 @@ WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt)
     {
         case PointerUpdateKind::LeftButtonPressed:
         case PointerUpdateKind::LeftButtonReleased:
-            return SDL_BUTTON_LEFT;
+            *button = SDL_BUTTON_LEFT;
+            *pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::LeftButtonPressed);
+            return SDL_TRUE;
 
         case PointerUpdateKind::RightButtonPressed:
         case PointerUpdateKind::RightButtonReleased:
-            return SDL_BUTTON_RIGHT;
+            *button = SDL_BUTTON_RIGHT;
+            *pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::RightButtonPressed);
+            return SDL_TRUE;
 
         case PointerUpdateKind::MiddleButtonPressed:
         case PointerUpdateKind::MiddleButtonReleased:
-            return SDL_BUTTON_MIDDLE;
+            *button = SDL_BUTTON_MIDDLE;
+            *pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::MiddleButtonPressed);
+            return SDL_TRUE;
 
         case PointerUpdateKind::XButton1Pressed:
         case PointerUpdateKind::XButton1Released:
-            return SDL_BUTTON_X1;
+            *button = SDL_BUTTON_X1;
+            *pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::XButton1Pressed);
+            return SDL_TRUE;
 
         case PointerUpdateKind::XButton2Pressed:
         case PointerUpdateKind::XButton2Released:
-            return SDL_BUTTON_X2;
+            *button = SDL_BUTTON_X2;
+            *pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::XButton2Pressed);
+            return SDL_TRUE;
 
         default:
             break;
     }
 #endif
 
-    return 0;
+    *button = 0;
+    *pressed = 0;
+    return SDL_FALSE;
 }
 
 //const char *
@@ -211,9 +223,10 @@ void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::Po
         return;
     }
 
-    Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
-
     if ( ! WINRT_IsTouchEvent(pointerPoint)) {
+        Uint8 button, pressed;
+        WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed);
+        SDL_assert(pressed == 1);
         SDL_SendMouseButton(window, 0, SDL_PRESSED, button);
     } else {
         Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne);
@@ -241,6 +254,12 @@ WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPo
     Windows::Foundation::Point windowPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, TransformToSDLWindowSize);
 
     if ( ! WINRT_IsTouchEvent(pointerPoint)) {
+        /* For some odd reason Moved events are used for multiple mouse buttons */
+        Uint8 button, pressed;
+        if (WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed)) {
+            SDL_SendMouseButton(window, 0, pressed, button);
+        }
+
         SDL_SendMouseMotion(window, 0, 0, (int)windowPoint.X, (int)windowPoint.Y);
     } else {
         SDL_SendTouchMotion(
@@ -259,9 +278,10 @@ void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::P
         return;
     }
 
-    Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
-
     if (!WINRT_IsTouchEvent(pointerPoint)) {
+        Uint8 button, pressed;
+        WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed);
+        SDL_assert(pressed == 0);
         SDL_SendMouseButton(window, 0, SDL_RELEASED, button);
     } else {
         Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne);