diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 2ec6b16be3e8..a5d44460fe52 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -708,31 +708,6 @@ static void EmuThreadJoin() { } struct InputStateTracker { - void TranslateMouseWheel() { - // SDL2 doesn't consider the mousewheel a button anymore - // so let's send the KEY_UP if it was moved after some frames - if (mouseWheelMovedUpFrames > 0) { - mouseWheelMovedUpFrames--; - if (mouseWheelMovedUpFrames == 0) { - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; - key.flags = KEY_UP; - NativeKey(key); - } - } - if (mouseWheelMovedDownFrames > 0) { - mouseWheelMovedDownFrames--; - if (mouseWheelMovedDownFrames == 0) { - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; - key.flags = KEY_UP; - NativeKey(key); - } - } - } - void MouseCaptureControl() { bool captureMouseCondition = g_Config.bMouseControl && ((GetUIState() == UISTATE_INGAME && g_Config.bMouseConfine) || g_Config.bMapMouse); if (mouseCaptured != captureMouseCondition) { @@ -745,8 +720,6 @@ struct InputStateTracker { } bool mouseDown; - int mouseWheelMovedUpFrames; - int mouseWheelMovedDownFrames; bool mouseCaptured; }; @@ -1019,11 +992,9 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta #endif if (event.wheel.y > 0) { key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; - inputTracker->mouseWheelMovedUpFrames = 5; NativeKey(key); } else if (event.wheel.y < 0) { key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; - inputTracker->mouseWheelMovedDownFrames = 5; NativeKey(key); } break; @@ -1448,8 +1419,6 @@ int main(int argc, char *argv[]) { if (!mainThreadIsRender) { // We should only be a message pump while (true) { - inputTracker.TranslateMouseWheel(); - SDL_Event event; while (SDL_PollEvent(&event)) { ProcessSDLEvent(window, event, &inputTracker); @@ -1461,7 +1430,6 @@ int main(int argc, char *argv[]) { inputTracker.MouseCaptureControl(); - { std::lock_guard guard(g_mutexWindow); if (g_windowState.update) { @@ -1470,8 +1438,6 @@ int main(int argc, char *argv[]) { } } } else while (true) { - inputTracker.TranslateMouseWheel(); - { SDL_Event event; while (SDL_PollEvent(&event)) { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 3f22acd0af9b..6d9ca17bf8ea 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -159,6 +159,7 @@ #include bool HandleGlobalMessage(UIMessage message, const std::string &value); +static void ProcessWheelRelease(InputKeyCode keyCode, double now, bool keyPress); ScreenManager *g_screenManager; std::string config_filename; @@ -1040,6 +1041,9 @@ void NativeFrame(GraphicsContext *graphicsContext) { double startTime = time_now_d(); + ProcessWheelRelease(NKCODE_EXT_MOUSEWHEEL_UP, startTime, false); + ProcessWheelRelease(NKCODE_EXT_MOUSEWHEEL_DOWN, startTime, false); + std::vector toProcess; { std::lock_guard lock(pendingMutex); @@ -1262,7 +1266,29 @@ void NativeTouch(const TouchInput &touch) { g_screenManager->touch(touch); } +// up, down +static double g_wheelReleaseTime[2]{}; +static const double RELEASE_TIME = 0.1; // about 3 frames at 30hz. + +static void ProcessWheelRelease(InputKeyCode keyCode, double now, bool keyPress) { + int dir = keyCode - NKCODE_EXT_MOUSEWHEEL_UP; + if (g_wheelReleaseTime[dir] != 0.0 && (keyPress || now >= g_wheelReleaseTime[dir])) { + g_wheelReleaseTime[dir] = 0.0; + KeyInput key{}; + key.deviceId = DEVICE_ID_MOUSE; + key.keyCode = keyCode; + key.flags = KEY_UP; + NativeKey(key); + } + + if (keyPress) { + g_wheelReleaseTime[dir] = now + RELEASE_TIME; + } +} + bool NativeKey(const KeyInput &key) { + double now = time_now_d(); + // VR actions if (IsVREnabled() && !UpdateVRKeys(key)) { return false; @@ -1290,12 +1316,19 @@ bool NativeKey(const KeyInput &key) { } #endif - bool retval = false; - if (g_screenManager) { - HLEPlugins::SetKey(key.keyCode, (key.flags & KEY_DOWN) ? 1 : 0); - retval = g_screenManager->key(key); + if (!g_screenManager) { + return false; } + // Handle releases of mousewheel keys. + if ((key.flags & KEY_DOWN) && key.deviceId == DEVICE_ID_MOUSE && (key.keyCode == NKCODE_EXT_MOUSEWHEEL_UP || key.keyCode == NKCODE_EXT_MOUSEWHEEL_DOWN)) { + ProcessWheelRelease(key.keyCode, now, true); + } + + HLEPlugins::SetKey(key.keyCode, (key.flags & KEY_DOWN) ? 1 : 0); + // Dispatch the key event. + bool retval = g_screenManager->key(key); + // The Mode key can have weird consequences on some devices, see #17245. if (key.keyCode == NKCODE_BUTTON_MODE) { // Tell the caller that we handled the key. diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index b3a9ff0a4b8d..00321de052cb 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -241,8 +241,10 @@ void PPSSPP_UWPMain::OnMouseWheel(float delta) { KeyInput keyInput{}; keyInput.keyCode = key; keyInput.deviceId = DEVICE_ID_MOUSE; - keyInput.flags = KEY_DOWN | KEY_UP; + keyInput.flags = KEY_DOWN; NativeKey(keyInput); + + // KEY_UP is now sent automatically afterwards for mouse wheel events, see NativeKey. } bool PPSSPP_UWPMain::OnHardwareButton(HardwareButton button) { diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 0b7f1afe5eb0..2cdafcaccf98 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -112,10 +112,8 @@ static std::wstring windowTitle; #define TIMER_CURSORUPDATE 1 #define TIMER_CURSORMOVEUPDATE 2 -#define TIMER_WHEELRELEASE 3 #define CURSORUPDATE_INTERVAL_MS 1000 #define CURSORUPDATE_MOVE_TIMESPAN_MS 500 -#define WHEELRELEASE_DELAY_MS 16 namespace MainWindow { @@ -267,17 +265,6 @@ namespace MainWindow } } - void ReleaseMouseWheel() { - // For simplicity release both wheel events - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.flags = KEY_UP; - key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; - NativeKey(key); - key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; - NativeKey(key); - } - static void HandleSizeChange(int newSizingType) { SavePosition(); Core_NotifyWindowHidden(false); @@ -927,10 +914,8 @@ namespace MainWindow } else { key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; } - // There's no separate keyup event for mousewheel events, - // so we release it with a slight delay. + // There's no release event, but we simulate it in NativeKey/NativeFrame. key.flags = KEY_DOWN | KEY_HASWHEELDELTA | (wheelDelta << 16); - SetTimer(hwndMain, TIMER_WHEELRELEASE, WHEELRELEASE_DELAY_MS, 0); NativeKey(key); } break; @@ -946,11 +931,6 @@ namespace MainWindow hideCursor = true; KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); return 0; - // Hack: need to release wheel event with a delay for games to register it was "pressed down". - case TIMER_WHEELRELEASE: - ReleaseMouseWheel(); - KillTimer(hWnd, TIMER_WHEELRELEASE); - return 0; } break; @@ -1045,7 +1025,6 @@ namespace MainWindow case WM_DESTROY: KillTimer(hWnd, TIMER_CURSORUPDATE); KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); - KillTimer(hWnd, TIMER_WHEELRELEASE); // Main window is gone, this tells the message loop to exit. PostQuitMessage(0); return 0; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 7b899d6101cc..acdf51e099a4 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1300,8 +1300,6 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeApp_mouseWheelEvent( // so we release it with a slight delay. key.flags = KEY_DOWN | KEY_HASWHEELDELTA | (wheelDelta << 16); NativeKey(key); - key.flags = KEY_UP; - NativeKey(key); return true; }