Skip to content

Commit

Permalink
Deliver mouse wheel events only once they reach a threshold
Browse files Browse the repository at this point in the history
On some devices (example Mac trackpad), many events are generated with small deltas.
This is overwhelming the EventSensor loop at image side to the detriment of user experience.
Workaround by letting the VM accumulate those deltas until they reach a threshold before delivering.

In case of high delta values, we generate a single value.
It's up to image side to handle those values
(until now, Squeak 5.3 just ignored them, VM is not to be blamed for that).

Note: 2 values are hardcoded for now
- the timeout for stopping accumulation (500ms)
- the threshold for delivering the event to the image.

The threshold could have been WHEEL_DELTA, but it gives bad sensitivity on my own device, so use only a fraction of that in the hope that it fits other devices too.
Please report if those tuning are inappropriate. We may add parameters in the future if necessary...
  • Loading branch information
nicolas-cellier-aka-nice committed Dec 26, 2019
1 parent 95e8219 commit b982355
Showing 1 changed file with 25 additions and 4 deletions.
29 changes: 25 additions & 4 deletions platforms/win32/vm/sqWin32Window.c
Expand Up @@ -271,6 +271,11 @@ LRESULT CALLBACK MainWndProcW(HWND hwnd,
static UINT nrClicks = 0;
UINT timeNow = 0;
UINT timeDelta = 0;
/* variables for accumulating mouse wheel deltas if too small */
static int hWheelDelta = 0;
static int vWheelDelta = 0;
static int prevHWheelTime = 0;
static int prevVWheelTime = 0;

MSG localMessage;
LPMSG messageTouse = NULL;
Expand Down Expand Up @@ -367,7 +372,15 @@ LRESULT CALLBACK MainWndProcW(HWND hwnd,
break;
case WM_MOUSEHWHEEL: {
if(inputSemaphoreIndex && sendWheelEvents) {
short zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
/* accumulate enough delta before sending the event to the image */
int limit = WHEEL_DELTA / 6; /* threshold for delivering events */
timeNow = GetMessageTime(); /* Win32 - gets time of last GetMessage() */
hWheelDelta = (timeNow - prevHWheelTime < 500 /* milliseconds */) ? hWheelDelta + zDelta : zDelta;
prevHWheelTime = timeNow;
if( - limit < hWheelDelta && hWheelDelta < limit ) break;
zDelta = hWheelDelta;
hWheelDelta = 0;
recordMouseWheelEvent(messageTouse,zDelta,0);
break;
} else {
Expand All @@ -378,7 +391,15 @@ LRESULT CALLBACK MainWndProcW(HWND hwnd,
case WM_MOUSEWHEEL: {
/* Record mouse wheel msgs as Up/Down arrow keypress + meta bits.
*/
short zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
/* accumulate enough delta before sending the event to the image */
int limit = WHEEL_DELTA / 6; /* threshold for delivering events */
timeNow = GetMessageTime(); /* Win32 - gets time of last GetMessage() */
vWheelDelta = (timeNow - prevVWheelTime < 500 /* milliseconds */) ? vWheelDelta + zDelta : zDelta;
prevVWheelTime = timeNow;
if( - limit < vWheelDelta && vWheelDelta < limit ) break;
zDelta = vWheelDelta;
vWheelDelta = 0;
if(inputSemaphoreIndex) {
if(sendWheelEvents) {
recordMouseWheelEvent(messageTouse,0,zDelta);
Expand All @@ -398,9 +419,9 @@ LRESULT CALLBACK MainWndProcW(HWND hwnd,
} else {
buttonState = 64;
if (zDelta < 0) {
recordVirtualKey(message,VK_DOWN,lParam);
recordVirtualKey(message,VK_DOWN,lParam);
} else {
recordVirtualKey(message,VK_UP,lParam);
recordVirtualKey(message,VK_UP,lParam);
}
/* state based stuff */
mousePosition.x = GET_X_LPARAM(lParam);
Expand Down

0 comments on commit b982355

Please sign in to comment.