winemac: Add the ability to disable high-resolution scrolling.
The Mac driver can generate scroll wheel events with values which are not integral multiples of WHEEL_DELTA. Apps should handle that by scrolling a corresponding non-integral multiple of what they'd do for a WHEEL_DELTA-valued scroll or, if they can't, then at least accumulate scroll distance until its magnitude exceeds WHEEL_DELTA and do a "chunky" scroll. However, many apps don't do that properly. They may scroll way too far/fast or even in the opposite direction. If the registry setting UsePreciseScrolling is set to "n", the Mac driver will do that accumulation and chunking itself to work around such broken app behavior.
This commit is contained in:
parent
757c57634e
commit
451915100a
|
@ -66,6 +66,9 @@ @interface WineApplicationController : NSObject <NSApplicationDelegate>
|
||||||
double mouseMoveDeltaX, mouseMoveDeltaY;
|
double mouseMoveDeltaX, mouseMoveDeltaY;
|
||||||
NSUInteger unmatchedMouseDowns;
|
NSUInteger unmatchedMouseDowns;
|
||||||
|
|
||||||
|
NSTimeInterval lastScrollTime;
|
||||||
|
double accumScrollX, accumScrollY;
|
||||||
|
|
||||||
NSMutableDictionary* originalDisplayModes;
|
NSMutableDictionary* originalDisplayModes;
|
||||||
NSMutableDictionary* latentDisplayModes;
|
NSMutableDictionary* latentDisplayModes;
|
||||||
BOOL displaysCapturedForFullscreen;
|
BOOL displaysCapturedForFullscreen;
|
||||||
|
|
|
@ -1725,7 +1725,7 @@ - (void) handleScrollWheel:(NSEvent*)theEvent
|
||||||
if (process)
|
if (process)
|
||||||
{
|
{
|
||||||
macdrv_event* event;
|
macdrv_event* event;
|
||||||
CGFloat x, y;
|
double x, y;
|
||||||
BOOL continuous = FALSE;
|
BOOL continuous = FALSE;
|
||||||
|
|
||||||
event = macdrv_create_event(MOUSE_SCROLL, window);
|
event = macdrv_create_event(MOUSE_SCROLL, window);
|
||||||
|
@ -1768,26 +1768,69 @@ - (void) handleScrollWheel:(NSEvent*)theEvent
|
||||||
/* The x,y values so far are in pixels. Win32 expects to receive some
|
/* The x,y values so far are in pixels. Win32 expects to receive some
|
||||||
fraction of WHEEL_DELTA == 120. By my estimation, that's roughly
|
fraction of WHEEL_DELTA == 120. By my estimation, that's roughly
|
||||||
6 times the pixel value. */
|
6 times the pixel value. */
|
||||||
event->mouse_scroll.x_scroll = 6 * x;
|
x *= 6;
|
||||||
event->mouse_scroll.y_scroll = 6 * y;
|
y *= 6;
|
||||||
|
|
||||||
if (!continuous)
|
if (use_precise_scrolling)
|
||||||
{
|
{
|
||||||
/* For non-continuous "clicky" wheels, if there was any motion, make
|
event->mouse_scroll.x_scroll = x;
|
||||||
sure there was at least WHEEL_DELTA motion. This is so, at slow
|
event->mouse_scroll.y_scroll = y;
|
||||||
speeds where the system's acceleration curve is actually reducing the
|
|
||||||
scroll distance, the user is sure to get some action out of each click.
|
|
||||||
For example, this is important for rotating though weapons in a
|
|
||||||
first-person shooter. */
|
|
||||||
if (0 < event->mouse_scroll.x_scroll && event->mouse_scroll.x_scroll < 120)
|
|
||||||
event->mouse_scroll.x_scroll = 120;
|
|
||||||
else if (-120 < event->mouse_scroll.x_scroll && event->mouse_scroll.x_scroll < 0)
|
|
||||||
event->mouse_scroll.x_scroll = -120;
|
|
||||||
|
|
||||||
if (0 < event->mouse_scroll.y_scroll && event->mouse_scroll.y_scroll < 120)
|
if (!continuous)
|
||||||
event->mouse_scroll.y_scroll = 120;
|
{
|
||||||
else if (-120 < event->mouse_scroll.y_scroll && event->mouse_scroll.y_scroll < 0)
|
/* For non-continuous "clicky" wheels, if there was any motion, make
|
||||||
event->mouse_scroll.y_scroll = -120;
|
sure there was at least WHEEL_DELTA motion. This is so, at slow
|
||||||
|
speeds where the system's acceleration curve is actually reducing the
|
||||||
|
scroll distance, the user is sure to get some action out of each click.
|
||||||
|
For example, this is important for rotating though weapons in a
|
||||||
|
first-person shooter. */
|
||||||
|
if (0 < event->mouse_scroll.x_scroll && event->mouse_scroll.x_scroll < 120)
|
||||||
|
event->mouse_scroll.x_scroll = 120;
|
||||||
|
else if (-120 < event->mouse_scroll.x_scroll && event->mouse_scroll.x_scroll < 0)
|
||||||
|
event->mouse_scroll.x_scroll = -120;
|
||||||
|
|
||||||
|
if (0 < event->mouse_scroll.y_scroll && event->mouse_scroll.y_scroll < 120)
|
||||||
|
event->mouse_scroll.y_scroll = 120;
|
||||||
|
else if (-120 < event->mouse_scroll.y_scroll && event->mouse_scroll.y_scroll < 0)
|
||||||
|
event->mouse_scroll.y_scroll = -120;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If it's been a while since the last scroll event or if the scrolling has
|
||||||
|
reversed direction, reset the accumulated scroll value. */
|
||||||
|
if ([theEvent timestamp] - lastScrollTime > 1)
|
||||||
|
accumScrollX = accumScrollY = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The accumulated scroll value is in the opposite direction/sign of the last
|
||||||
|
scroll. That's because it's the "debt" resulting from over-scrolling in
|
||||||
|
that direction. We accumulate by adding in the scroll amount and then, if
|
||||||
|
it has the same sign as the scroll value, we subtract any whole or partial
|
||||||
|
WHEEL_DELTAs, leaving it 0 or the opposite sign. So, the user switched
|
||||||
|
scroll direction if the accumulated debt and the new scroll value have the
|
||||||
|
same sign. */
|
||||||
|
if ((accumScrollX < 0 && x < 0) || (accumScrollX > 0 && x > 0))
|
||||||
|
accumScrollX = 0;
|
||||||
|
if ((accumScrollY < 0 && y < 0) || (accumScrollY > 0 && y > 0))
|
||||||
|
accumScrollY = 0;
|
||||||
|
}
|
||||||
|
lastScrollTime = [theEvent timestamp];
|
||||||
|
|
||||||
|
accumScrollX += x;
|
||||||
|
accumScrollY += y;
|
||||||
|
|
||||||
|
if (accumScrollX > 0 && x > 0)
|
||||||
|
event->mouse_scroll.x_scroll = 120 * ceil(accumScrollX / 120);
|
||||||
|
if (accumScrollX < 0 && x < 0)
|
||||||
|
event->mouse_scroll.x_scroll = 120 * -ceil(-accumScrollX / 120);
|
||||||
|
if (accumScrollY > 0 && y > 0)
|
||||||
|
event->mouse_scroll.y_scroll = 120 * ceil(accumScrollY / 120);
|
||||||
|
if (accumScrollY < 0 && y < 0)
|
||||||
|
event->mouse_scroll.y_scroll = 120 * -ceil(-accumScrollY / 120);
|
||||||
|
|
||||||
|
accumScrollX -= event->mouse_scroll.x_scroll;
|
||||||
|
accumScrollY -= event->mouse_scroll.y_scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->mouse_scroll.x_scroll || event->mouse_scroll.y_scroll)
|
if (event->mouse_scroll.x_scroll || event->mouse_scroll.y_scroll)
|
||||||
|
|
|
@ -148,6 +148,7 @@
|
||||||
extern int right_option_is_alt DECLSPEC_HIDDEN;
|
extern int right_option_is_alt DECLSPEC_HIDDEN;
|
||||||
extern int allow_immovable_windows DECLSPEC_HIDDEN;
|
extern int allow_immovable_windows DECLSPEC_HIDDEN;
|
||||||
extern int cursor_clipping_locks_windows DECLSPEC_HIDDEN;
|
extern int cursor_clipping_locks_windows DECLSPEC_HIDDEN;
|
||||||
|
extern int use_precise_scrolling DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
extern int macdrv_start_cocoa_app(unsigned long long tickcount) DECLSPEC_HIDDEN;
|
extern int macdrv_start_cocoa_app(unsigned long long tickcount) DECLSPEC_HIDDEN;
|
||||||
extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLSPEC_HIDDEN;
|
extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -56,6 +56,7 @@ BOOL allow_software_rendering = FALSE;
|
||||||
BOOL disable_window_decorations = FALSE;
|
BOOL disable_window_decorations = FALSE;
|
||||||
int allow_immovable_windows = TRUE;
|
int allow_immovable_windows = TRUE;
|
||||||
int cursor_clipping_locks_windows = TRUE;
|
int cursor_clipping_locks_windows = TRUE;
|
||||||
|
int use_precise_scrolling = TRUE;
|
||||||
HMODULE macdrv_module = 0;
|
HMODULE macdrv_module = 0;
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,6 +180,9 @@ static void setup_options(void)
|
||||||
if (!get_config_key(hkey, appkey, "CursorClippingLocksWindows", buffer, sizeof(buffer)))
|
if (!get_config_key(hkey, appkey, "CursorClippingLocksWindows", buffer, sizeof(buffer)))
|
||||||
cursor_clipping_locks_windows = IS_OPTION_TRUE(buffer[0]);
|
cursor_clipping_locks_windows = IS_OPTION_TRUE(buffer[0]);
|
||||||
|
|
||||||
|
if (!get_config_key(hkey, appkey, "UsePreciseScrolling", buffer, sizeof(buffer)))
|
||||||
|
use_precise_scrolling = IS_OPTION_TRUE(buffer[0]);
|
||||||
|
|
||||||
if (appkey) RegCloseKey(appkey);
|
if (appkey) RegCloseKey(appkey);
|
||||||
if (hkey) RegCloseKey(hkey);
|
if (hkey) RegCloseKey(hkey);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue