summaryrefslogtreecommitdiff
path: root/hw/xquartz
diff options
context:
space:
mode:
authorJeremy Huddleston <jeremyhu@apple.com>2012-04-19 18:48:22 -0700
committerJeremy Huddleston <jeremyhu@apple.com>2012-04-26 21:07:09 -0700
commit0d13e62da2b3527db7b3b6de91464015eb20a514 (patch)
tree31c7041c3bebb3e1b4e674f1e95101054e730521 /hw/xquartz
parent287f8271a3af18fb1a56a761fa02ec76148d9e32 (diff)
XQuartz: Add a hack to better handle clicky wheel scroll mice
We loose information from AppKit being in our way. Before adopting smooth scrolling, we always rounded-up the number of scroll button clicks per NSEvent. Now, the scroll value is accumulated in the dix, and clicky scroll wheels with legacy X11 clients are seeing an accumulation of error due to so many translations (button press to smooth scrolling value in AppKit, passed to the dix, and then synthesized into a button press). This attempts to make the situation better. http://xquartz.macosforge.org/trac/ticket/562 Signed-off-by: Jeremy Huddleston <jeremyhu@apple.com> (cherry picked from commit 662d41acdde1dcb9774fbe4054e251c708acaffe)
Diffstat (limited to 'hw/xquartz')
-rw-r--r--hw/xquartz/X11Application.m111
1 files changed, 109 insertions, 2 deletions
diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m
index f251d238c..3517c49a8 100644
--- a/hw/xquartz/X11Application.m
+++ b/hw/xquartz/X11Application.m
@@ -1590,8 +1590,28 @@ handle_mouse:
case NSScrollWheel:
{
- float deltaX = [e deltaX];
- float deltaY = [e deltaY];
+ CGFloat deltaX = [e deltaX];
+ CGFloat deltaY = [e deltaY];
+ CGEventRef cge = [e CGEvent];
+ BOOL isContinuous =
+ CGEventGetIntegerValueField(cge, kCGScrollWheelEventIsContinuous);
+
+#if 0
+ /* Scale the scroll value by line height */
+ CGEventSourceRef source = CGEventCreateSourceFromEvent(cge);
+ if (source) {
+ double lineHeight = CGEventSourceGetPixelsPerLine(source);
+ CFRelease(source);
+
+ /* There's no real reason for the 1/5 ratio here other than that
+ * it feels like a good ratio after some testing.
+ */
+
+ deltaX *= lineHeight / 5.0;
+ deltaY *= lineHeight / 5.0;
+ }
+#endif
+
#if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION == 0
/* If we're in the background, we need to send a MotionNotify event
* first, since we aren't getting them on background mouse motion
@@ -1611,6 +1631,93 @@ handle_mouse:
deltaY *= -1;
}
#endif
+ /* This hack is in place to better deal with "clicky" scroll wheels:
+ * http://xquartz.macosforge.org/trac/ticket/562
+ */
+ if (!isContinuous) {
+ static NSTimeInterval lastScrollTime = 0.0;
+
+ /* These store how much extra we have already scrolled.
+ * ie, this is how much we ignore on the next event.
+ */
+ static double deficit_x = 0.0;
+ static double deficit_y = 0.0;
+
+ /* If we have past a second since the last scroll, wipe the slate
+ * clean
+ */
+ if ([e timestamp] - lastScrollTime > 1.0) {
+ deficit_x = deficit_y = 0.0;
+ }
+ lastScrollTime = [e timestamp];
+
+ if (deltaX != 0.0) {
+ /* If we changed directions, wipe the slate clean */
+ if ((deficit_x < 0.0 && deltaX > 0.0) ||
+ (deficit_x > 0.0 && deltaX < 0.0)) {
+ deficit_x = 0.0;
+ }
+
+ /* Eat up the deficit, but ensure that something is
+ * always sent
+ */
+ if (fabs(deltaX) > fabs(deficit_x)) {
+ deltaX -= deficit_x;
+
+ if (deltaX > 0.0) {
+ deficit_x = ceil(deltaX) - deltaX;
+ deltaX = ceil(deltaX);
+ } else {
+ deficit_x = floor(deltaX) - deltaX;
+ deltaX = floor(deltaX);
+ }
+ } else {
+ deficit_x -= deltaX;
+
+ if (deltaX > 0.0) {
+ deltaX = 1.0;
+ } else {
+ deltaX = -1.0;
+ }
+
+ deficit_x += deltaX;
+ }
+ }
+
+ if (deltaY != 0.0) {
+ /* If we changed directions, wipe the slate clean */
+ if ((deficit_y < 0.0 && deltaY > 0.0) ||
+ (deficit_y > 0.0 && deltaY < 0.0)) {
+ deficit_y = 0.0;
+ }
+
+ /* Eat up the deficit, but ensure that something is
+ * always sent
+ */
+ if (fabs(deltaY) > fabs(deficit_y)) {
+ deltaY -= deficit_y;
+
+ if (deltaY > 0.0) {
+ deficit_y = ceil(deltaY) - deltaY;
+ deltaY = ceil(deltaY);
+ } else {
+ deficit_y = floor(deltaY) - deltaY;
+ deltaY = floor(deltaY);
+ }
+ } else {
+ deficit_y -= deltaY;
+
+ if (deltaY > 0.0) {
+ deltaY = 1.0;
+ } else {
+ deltaY = -1.0;
+ }
+
+ deficit_y += deltaY;
+ }
+ }
+ }
+
DarwinSendScrollEvents(deltaX, deltaY);
break;
}