Skip to content

Commit

Permalink
Merge pull request #18568 from hrydgard/mouse-wheel-repeat
Browse files Browse the repository at this point in the history
Mouse wheel: Centralize the sending of KEY_UP events on a timer.
  • Loading branch information
hrydgard committed Dec 17, 2023
2 parents 6140321 + 818471a commit 06e92e9
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 63 deletions.
34 changes: 0 additions & 34 deletions SDL/SDLMain.cpp
Expand Up @@ -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) {
Expand All @@ -745,8 +720,6 @@ struct InputStateTracker {
}

bool mouseDown;
int mouseWheelMovedUpFrames;
int mouseWheelMovedDownFrames;
bool mouseCaptured;
};

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -1461,7 +1430,6 @@ int main(int argc, char *argv[]) {

inputTracker.MouseCaptureControl();


{
std::lock_guard<std::mutex> guard(g_mutexWindow);
if (g_windowState.update) {
Expand All @@ -1470,8 +1438,6 @@ int main(int argc, char *argv[]) {
}
}
} else while (true) {
inputTracker.TranslateMouseWheel();

{
SDL_Event event;
while (SDL_PollEvent(&event)) {
Expand Down
41 changes: 37 additions & 4 deletions UI/NativeApp.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
4 changes: 3 additions & 1 deletion UWP/PPSSPP_UWPMain.cpp
Expand Up @@ -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) {
Expand Down
23 changes: 1 addition & 22 deletions Windows/MainWindow.cpp
Expand Up @@ -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
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
2 changes: 0 additions & 2 deletions android/jni/app-android.cpp
Expand Up @@ -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;
}

Expand Down

0 comments on commit 06e92e9

Please sign in to comment.