Mouse wheel: Centralize the sending of KEY_UP events on a timer.

This commit is contained in:
Henrik Rydgård 2023-12-17 19:40:59 +01:00
parent e5af1f8bd0
commit 818471a2d7
5 changed files with 41 additions and 63 deletions

View File

@ -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<std::mutex> 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)) {

View File

@ -159,6 +159,7 @@
#include <Core/HLE/Plugins.h>
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<PendingMessage> toProcess;
{
std::lock_guard<std::mutex> 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.

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}