Xi/exevents.c | 174 ++++++++++++++++++++++++---- dix/devices.c | 2 dix/dispatch.c | 5 dix/events.c | 60 +++++++-- dix/getevents.c | 3 dix/touch.c | 122 +++++++++++-------- glx/glapi_gentable.c | 2 hw/xfree86/modes/xf86Rotate.c | 11 + hw/xquartz/X11Application.m | 154 +++++++++++++++++++++--- hw/xquartz/console_redirect.c | 2 hw/xquartz/darwin.c | 57 +++++---- hw/xquartz/darwinEvents.c | 210 ++++++++++++++-------------------- hw/xquartz/darwinEvents.h | 13 -- hw/xquartz/mach-startup/bundle-main.c | 2 hw/xquartz/xpr/xprFrame.c | 2 include/input.h | 6 os/WaitFor.c | 18 ++ xkb/xkbActions.c | 26 +++- 18 files changed, 594 insertions(+), 275 deletions(-)
New commits: commit 22a1953c4a2747d637bb926034f11134809b8d06 Author: Jeremy Huddleston <jerem...@apple.com> Date: Thu Apr 26 21:17:54 2012 -0700 XQuartz: Make sure we tell startx the correct server binary to use in our fallback path With multiple servers installed, we can't be certain if X is Xorg or Xquartz Signed-off-by: Jeremy Huddleston <jerem...@apple.com> (cherry picked from commit 93d6ba5b711cbd3f502d83e54c9739856d2e6f2a) diff --git a/hw/xquartz/mach-startup/bundle-main.c b/hw/xquartz/mach-startup/bundle-main.c index d1ad6f7..cabdf1e 100644 --- a/hw/xquartz/mach-startup/bundle-main.c +++ b/hw/xquartz/mach-startup/bundle-main.c @@ -78,7 +78,7 @@ FatalError(const char *f, ...) _X_ATTRIBUTE_PRINTF(1, 2) _X_NORETURN; extern int noPanoramiXExtension; #define DEFAULT_CLIENT X11BINDIR "/xterm" -#define DEFAULT_STARTX X11BINDIR "/startx" +#define DEFAULT_STARTX X11BINDIR "/startx -- " X11BINDIR "/Xquartz" #define DEFAULT_SHELL "/bin/sh" #ifndef BUILD_DATE commit 90299556db24543bb7365e8c2897deca3aa219e7 Author: Peter Hutterer <peter.hutte...@who-t.net> Date: Mon Apr 30 10:01:48 2012 +1000 dix: when disabling a device, release all buttons and keys A suspend-induced device disable may happen before the device gets to see the button release event. On resume, the server's internal state still has some buttons pressed, causing inconsistent behaviour. Force the release and the matching events to be sent to the client. Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> Reviewed-by: Chase Douglas <chase.doug...@canonical.com> (cherry picked from commit f3410b97cf9b48a47bee3d15d232f8a88e75f4ef) Conflicts: dix/devices.c diff --git a/dix/devices.c b/dix/devices.c index 0125504..d0e99bd 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -432,6 +432,8 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent) if (*prev != dev) return FALSE; + ReleaseButtonsAndKeys(dev); + /* float attached devices */ if (IsMaster(dev)) { for (other = inputInfo.devices; other; other = other->next) { commit b53cdf4c53f0787ed41281278877e0405fcb2674 Author: Peter Hutterer <peter.hutte...@who-t.net> Date: Fri Apr 27 16:31:17 2012 +1000 dix: don't emulate scroll events for non-existing axes (#47281) Test case: - create a device with REL_HWHEEL and ABS_X and ABS_Y. evdev 2.7.0 will set that up as device with 1 relative axis - move pointer to VGA1 - xrandr --output VGA1 --off Warps the pointer to the new spot and calls GPE with the x/y mask bits set. When running through the loop to check for scroll event, this overruns the axes and may try to emulate scroll events based on random garbage in the memory. If that memory contained non-zero for the scroll type but near-zero for the increment field, the server would hang in an infinite loop. This was the trigger for this suggested, never-merged, patch here: http://patchwork.freedesktop.org/patch/9543/ X.Org Bug 47281 <http://bugs.freedesktop.org/show_bug.cgi?id=47281> Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> Reviewed-by: Chase Douglas <chase.doug...@canonical.com> (cherry picked from commit af88b43f9e604157b74270d609c08bdfa256a792) diff --git a/dix/getevents.c b/dix/getevents.c index fa85fe7..4e0af45 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -1574,6 +1574,9 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, /* Now turn the smooth-scrolling axes back into emulated button presses * for legacy clients, based on the integer delta between before and now */ for (i = 0; i < valuator_mask_size(&mask); i++) { + if (i >= pDev->valuator->numAxes) + break; + if (!valuator_mask_isset(&mask, i)) continue; commit 9ddf9e2388f9ac5f4c325304ab0c59c1fd5e2024 Author: Peter Hutterer <peter.hutte...@who-t.net> Date: Fri Apr 27 10:52:39 2012 +1000 os: make timers signal-safe If TimerSet() is called from a signal handler (synaptics tap handling code) may result in list corruption if we're currently inside TimerSet(). See backtrace in https://bugzilla.redhat.com/show_bug.cgi?id=814869 Block signals for all list manipulations in the timers. Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> Reviewed-by: Chase Douglas <chase.doug...@canonical.com> (cherry picked from commit 08962951de969b9d8c870af8b6e47303dc0decfd) diff --git a/os/WaitFor.c b/os/WaitFor.c index 4c3be34..59f3af6 100644 --- a/os/WaitFor.c +++ b/os/WaitFor.c @@ -382,6 +382,7 @@ CheckAllTimers(void) OsTimerPtr timer; CARD32 now; + OsBlockSignals(); start: now = GetTimeInMillis(); @@ -391,6 +392,7 @@ CheckAllTimers(void) goto start; } } + OsReleaseSignals(); } static void @@ -398,11 +400,13 @@ DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev) { CARD32 newTime; + OsBlockSignals(); *prev = timer->next; timer->next = NULL; newTime = (*timer->callback) (timer, now, timer->arg); if (newTime) TimerSet(timer, 0, newTime, timer->callback, timer->arg); + OsReleaseSignals(); } OsTimerPtr @@ -418,6 +422,7 @@ TimerSet(OsTimerPtr timer, int flags, CARD32 millis, return NULL; } else { + OsBlockSignals(); for (prev = &timers; *prev; prev = &(*prev)->next) { if (*prev == timer) { *prev = timer->next; @@ -426,6 +431,7 @@ TimerSet(OsTimerPtr timer, int flags, CARD32 millis, break; } } + OsReleaseSignals(); } if (!millis) return timer; @@ -445,26 +451,32 @@ TimerSet(OsTimerPtr timer, int flags, CARD32 millis, if (!millis) return timer; } + OsBlockSignals(); for (prev = &timers; *prev && (int) ((*prev)->expires - millis) <= 0; prev = &(*prev)->next); timer->next = *prev; *prev = timer; + OsReleaseSignals(); return timer; } Bool TimerForce(OsTimerPtr timer) { + int rc = FALSE; OsTimerPtr *prev; + OsBlockSignals(); for (prev = &timers; *prev; prev = &(*prev)->next) { if (*prev == timer) { DoTimer(timer, GetTimeInMillis(), prev); - return TRUE; + rc = TRUE; + break; } } - return FALSE; + OsReleaseSignals(); + return rc; } void @@ -474,12 +486,14 @@ TimerCancel(OsTimerPtr timer) if (!timer) return; + OsBlockSignals(); for (prev = &timers; *prev; prev = &(*prev)->next) { if (*prev == timer) { *prev = timer->next; break; } } + OsReleaseSignals(); } void commit 345761be71b86b687f407eb8de746a33bab7ad2e Author: Chase Douglas <chase.doug...@canonical.com> Date: Fri Apr 20 11:08:15 2012 -0700 TouchListenerAcceptReject: Warn and return early on bad listener index Signed-off-by: Chase Douglas <chase.doug...@canonical.com> Reviewed-by: Bryce Harrington <br...@canonical.com> Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> (cherry picked from commit 5c361d59c5031d9b3f7f9093a52d2b1ff4d9ae5f) diff --git a/dix/touch.c b/dix/touch.c index dd16367..401cb98 100644 --- a/dix/touch.c +++ b/dix/touch.c @@ -966,6 +966,11 @@ TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti, int listener, int nev; int i; + BUG_WARN(listener < 0); + BUG_WARN(listener >= ti->num_listeners); + if (listener < 0 || listener >= ti->num_listeners) + return BadMatch; + if (listener > 0) { if (mode == XIRejectTouch) TouchRejected(dev, ti, ti->listeners[listener].listener, NULL); commit ed33772a0d3ace5844e157ae78885ded000819ea Author: Michal Suchanek <hramr...@gmail.com> Date: Wed Mar 28 18:12:39 2012 -0700 xfree86: workaround crash on close Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=41653 Signed-off-by: Michal Suchanek <hramr...@gmail.com> Reviewed-by: Jeremy Huddleston <jerem...@apple.com> Tested-by: Knut Petersen <knut_peter...@t-online.de> (cherry picked from commit fa6dddc6ce51c1b7a43fb379fb2a19550f6c8683) diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c index 85d7557..cbc8687 100644 --- a/hw/xfree86/modes/xf86Rotate.c +++ b/hw/xfree86/modes/xf86Rotate.c @@ -290,14 +290,19 @@ xf86RotateDestroy(xf86CrtcPtr crtc) * Clean up damage structures when no crtcs are rotated */ if (xf86_config->rotation_damage) { + DrawablePtr screenDrawable = NULL; + if (pScreen && pScreen->root) + screenDrawable = &pScreen->root->drawable; /* Free damage structure */ if (xf86_config->rotation_damage_registered) { - DamageUnregister(&pScreen->root->drawable, - xf86_config->rotation_damage); + if (screenDrawable) + DamageUnregister(screenDrawable, + xf86_config->rotation_damage); xf86_config->rotation_damage_registered = FALSE; DisableLimitedSchedulingLatency(); } - DamageDestroy(xf86_config->rotation_damage); + if (screenDrawable) + DamageDestroy(xf86_config->rotation_damage); xf86_config->rotation_damage = NULL; } } commit e4dbdee392c78de13fab03c3826f9453f42a8a46 Author: Jonas Maebe <jonas.ma...@elis.ugent.be> Date: Sun Apr 22 20:52:47 2012 -0700 glapi: Correct size of allocated _glapi_table struct The __glapi_gentable_set_remaining_noop() routine treats the _glapi_struct as an array of _glapi_get_dispatch_table_size() pointers, so we have to allocate _glapi_get_dispatch_table_size()*sizeof(void*) bytes rather than sizeof(struct _glapi_struct) bytes. Signed-off-by: Jonas Maebe <jonas.ma...@elis.ugent.be> Reviewed-by: Jeremy Huddleston <jerem...@apple.com> (cherry picked from commit adcb48a29dcb3f32ff570551de4b014775c1e147) diff --git a/glx/glapi_gentable.c b/glx/glapi_gentable.c index 1fb1431..4b28015 100644 --- a/glx/glapi_gentable.c +++ b/glx/glapi_gentable.c @@ -113,7 +113,7 @@ __glapi_gentable_set_remaining_noop(struct _glapi_table *disp) struct _glapi_table * _glapi_create_table_from_handle(void *handle, const char *symbol_prefix) { - struct _glapi_table *disp = calloc(1, sizeof(struct _glapi_table)); + struct _glapi_table *disp = calloc(_glapi_get_dispatch_table_size(), sizeof(void*)); char symboln[512]; if (!disp) commit 6b45dff0240729a78a43cc74f1631b2dd5a0d6b3 Author: Jeremy Huddleston <jerem...@apple.com> Date: Thu Apr 19 16:38:06 2012 -0700 XQuartz: darwinPointer now sends both absolute and relative motion This should hopefully help out wine clients that were continuing to have issues after the earlier changes. http://xquartz.macosforge.org/trac/ticket/548 Signed-off-by: Jeremy Huddleston <jerem...@apple.com> (cherry picked from commit e34519e525559b01a63d26639f13f0487468de28) diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m index 3517c49..b686b00 100644 --- a/hw/xquartz/X11Application.m +++ b/hw/xquartz/X11Application.m @@ -214,7 +214,8 @@ message_kit_thread(SEL selector, NSObject *arg) if (state) { if (bgMouseLocationUpdated) { DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, - bgMouseLocation.x, bgMouseLocation.y); + bgMouseLocation.x, bgMouseLocation.y, + 0.0, 0.0); bgMouseLocationUpdated = FALSE; } DarwinSendDDXEvent(kXquartzActivate, 0); @@ -1547,14 +1548,16 @@ handle_mouse: if (bgMouseLocationUpdated) { if (!(ev_type == MotionNotify && ev_button == 0)) { DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, - location.x, location.y); + location.x, location.y, + 0.0, 0.0); } bgMouseLocationUpdated = FALSE; } if (pDev == darwinPointer) { DarwinSendPointerEvents(pDev, ev_type, ev_button, - location.x, location.y); + location.x, location.y, + [e deltaX], [e deltaY]); } else { DarwinSendTabletEvents(pDev, ev_type, ev_button, location.x, location.y, pressure, @@ -1619,7 +1622,8 @@ handle_mouse: if (!XQuartzServerVisible && noTestExtensions) { bgMouseLocationUpdated = FALSE; DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, - location.x, location.y); + location.x, location.y, + 0.0, 0.0); } #endif #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 diff --git a/hw/xquartz/darwin.c b/hw/xquartz/darwin.c index 2d5174a..74e11fe 100644 --- a/hw/xquartz/darwin.c +++ b/hw/xquartz/darwin.c @@ -307,7 +307,7 @@ static int DarwinMouseProc(DeviceIntPtr pPointer, int what) { #define NBUTTONS 3 -#define NAXES 4 +#define NAXES 6 // 3 buttons: left, middle, right CARD8 map[NBUTTONS + 1] = { 0, 1, 2, 3}; Atom btn_labels[NBUTTONS] = { 0 }; @@ -321,10 +321,12 @@ DarwinMouseProc(DeviceIntPtr pPointer, int what) btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); - axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); - axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); - axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL); - axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HWHEEL); + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); + axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); + axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); + axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL); + axes_labels[5] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HWHEEL); // Set button map. InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS, @@ -332,21 +334,27 @@ DarwinMouseProc(DeviceIntPtr pPointer, int what) (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), NAXES, axes_labels); - InitValuatorAxisStruct(pPointer, 0, axes_labels[0], + InitValuatorAxisStruct(pPointer, 0, axes_labels[0], NO_AXIS_LIMITS, NO_AXIS_LIMITS, - 1, 0, 1, Relative); - InitValuatorAxisStruct(pPointer, 1, axes_labels[1], + 0, 0, 0, Absolute); + InitValuatorAxisStruct(pPointer, 1, axes_labels[1], NO_AXIS_LIMITS, NO_AXIS_LIMITS, - 1, 0, 1, Relative); + 0, 0, 0, Absolute); InitValuatorAxisStruct(pPointer, 2, axes_labels[2], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative); InitValuatorAxisStruct(pPointer, 3, axes_labels[3], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative); + InitValuatorAxisStruct(pPointer, 4, axes_labels[4], + NO_AXIS_LIMITS, NO_AXIS_LIMITS, + 1, 0, 1, Relative); + InitValuatorAxisStruct(pPointer, 5, axes_labels[5], + NO_AXIS_LIMITS, NO_AXIS_LIMITS, + 1, 0, 1, Relative); - SetScrollValuator(pPointer, 2, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_PREFERRED); - SetScrollValuator(pPointer, 3, SCROLL_TYPE_HORIZONTAL, -1.0, SCROLL_FLAG_NONE); + SetScrollValuator(pPointer, 4, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_PREFERRED); + SetScrollValuator(pPointer, 5, SCROLL_TYPE_HORIZONTAL, -1.0, SCROLL_FLAG_NONE); break; case DEVICE_ON: @@ -397,23 +405,24 @@ DarwinTabletProc(DeviceIntPtr pPointer, int what) axes_labels); InitProximityClassDeviceStruct(pPointer); - InitValuatorAxisStruct(pPointer, 0, axes_labels[0], 0, - XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, - Absolute); - InitValuatorAxisStruct(pPointer, 1, axes_labels[1], 0, - XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, - Absolute); - InitValuatorAxisStruct(pPointer, 2, axes_labels[2], 0, - XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, - Absolute); + InitValuatorAxisStruct(pPointer, 0, axes_labels[0], + 0, XQUARTZ_VALUATOR_LIMIT, + 1, 0, 1, Absolute); + InitValuatorAxisStruct(pPointer, 1, axes_labels[1], + 0, XQUARTZ_VALUATOR_LIMIT, + 1, 0, 1, Absolute); + InitValuatorAxisStruct(pPointer, 2, axes_labels[2], + 0, XQUARTZ_VALUATOR_LIMIT, + 1, 0, 1, Absolute); InitValuatorAxisStruct(pPointer, 3, axes_labels[3], -XQUARTZ_VALUATOR_LIMIT, - XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, - Absolute); + XQUARTZ_VALUATOR_LIMIT, + 1, 0, 1, Absolute); InitValuatorAxisStruct(pPointer, 4, axes_labels[4], -XQUARTZ_VALUATOR_LIMIT, - XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, - Absolute); + XQUARTZ_VALUATOR_LIMIT, + 1, 0, 1, Absolute); + // pPointer->use = IsXExtensionDevice; break; diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c index 25f011b..b41c6fd 100644 --- a/hw/xquartz/darwinEvents.c +++ b/hw/xquartz/darwinEvents.c @@ -74,12 +74,6 @@ #include <IOKit/hidsystem/IOLLEvent.h> -/* Fake button press/release for scroll wheel move. */ -#define SCROLLWHEELUPFAKE 4 -#define SCROLLWHEELDOWNFAKE 5 -#define SCROLLWHEELLEFTFAKE 6 -#define SCROLLWHEELRIGHTFAKE 7 - #include <X11/extensions/applewmconst.h> #include "applewmExt.h" @@ -497,12 +491,6 @@ DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button, pointer_x -= darwinMainScreenX + screen->x; pointer_y -= darwinMainScreenY + screen->y; - if (pointer_x < 0.0) - pointer_x = 0.0; - - if (pointer_y < 0.0) - pointer_y = 0.0; - /* Adjust our pointer location to the [0,1] range */ pointer_x = pointer_x / (double)screenInfo.width; pointer_y = pointer_y / (double)screenInfo.height; @@ -528,7 +516,8 @@ DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button, void DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, - double pointer_x, double pointer_y) + double pointer_x, double pointer_y, + double pointer_dx, double pointer_dy) { static int darwinFakeMouseButtonDown = 0; ScreenPtr screen; @@ -553,7 +542,7 @@ DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, /* We're currently "down" with another button, so release it first */ DarwinSendPointerEvents(pDev, ButtonRelease, darwinFakeMouseButtonDown, - pointer_x, pointer_y); + pointer_x, pointer_y, 0.0, 0.0); darwinFakeMouseButtonDown = 0; } if (darwin_all_modifier_flags & darwinFakeMouse2Mask) { @@ -591,22 +580,23 @@ DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, pointer_x -= darwinMainScreenX + screen->x; pointer_y -= darwinMainScreenY + screen->y; - if (pointer_x < 0.0) - pointer_x = 0.0; - - if (pointer_y < 0.0) - pointer_y = 0.0; - valuator_mask_zero(&valuators); valuator_mask_set_double(&valuators, 0, pointer_x); valuator_mask_set_double(&valuators, 1, pointer_y); + if (ev_type == MotionNotify) { + if (pointer_dx != 0.0) + valuator_mask_set_double(&valuators, 2, pointer_dx); + if (pointer_dy != 0.0) + valuator_mask_set_double(&valuators, 3, pointer_dy); + } + darwinEvents_lock(); { QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE, &valuators); DarwinPokeEQ(); - } darwinEvents_unlock(); + } darwinEvents_unlock(); } void @@ -647,8 +637,8 @@ DarwinSendScrollEvents(double scroll_x, double scroll_y) { } valuator_mask_zero(&valuators); - valuator_mask_set_double(&valuators, 2, scroll_y); - valuator_mask_set_double(&valuators, 3, scroll_x); + valuator_mask_set_double(&valuators, 4, scroll_y); + valuator_mask_set_double(&valuators, 5, scroll_x); darwinEvents_lock(); { diff --git a/hw/xquartz/darwinEvents.h b/hw/xquartz/darwinEvents.h index 812a5dc..448e730 100644 --- a/hw/xquartz/darwinEvents.h +++ b/hw/xquartz/darwinEvents.h @@ -49,7 +49,8 @@ DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button, double tilt_x, double tilt_y); void DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, - double pointer_x, double pointer_y); + double pointer_x, double pointer_y, + double pointer_dx, double pointer_dy); void DarwinSendKeyboardEvents(int ev_type, int keycode); void commit 0d13e62da2b3527db7b3b6de91464015eb20a514 Author: Jeremy Huddleston <jerem...@apple.com> Date: Thu Apr 19 18:48:22 2012 -0700 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 <jerem...@apple.com> (cherry picked from commit 662d41acdde1dcb9774fbe4054e251c708acaffe) diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m index f251d23..3517c49 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; } commit 287f8271a3af18fb1a56a761fa02ec76148d9e32 Author: Jeremy Huddleston <jerem...@apple.com> Date: Thu Apr 19 16:20:30 2012 -0700 XQuartz: Use screenInfo.{width,height} instead of grabbing it from the first screen Signed-off-by: Jeremy Huddleston <jerem...@apple.com> (cherry picked from commit eda85290ae47d8dd497ef9335d10268bbe3e02a0) diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c index 9fc23a3..25f011b 100644 --- a/hw/xquartz/darwinEvents.c +++ b/hw/xquartz/darwinEvents.c @@ -504,8 +504,8 @@ DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button, pointer_y = 0.0; /* Adjust our pointer location to the [0,1] range */ - pointer_x = pointer_x / (double)screenInfo.screens[0]->width; - pointer_y = pointer_y / (double)screenInfo.screens[0]->height; + pointer_x = pointer_x / (double)screenInfo.width; + pointer_y = pointer_y / (double)screenInfo.height; valuator_mask_zero(&valuators); valuator_mask_set_double(&valuators, 0, XQUARTZ_VALUATOR_LIMIT * pointer_x); commit 67cc65ba3ca35b4eb9592e1e6f299938509cddec Author: Jeremy Huddleston <jerem...@apple.com> Date: Wed Apr 18 17:50:55 2012 -0700 XQuartz: Separate out tablet and mouse event delivery into separate functions This should have no immediate impact aside from fake mouse buttons no longer working with tablets (where they aren't needed or desired anyways). This prepares us for future changes. Signed-off-by: Jeremy Huddleston <jerem...@apple.com> (cherry picked from commit b99586c9086ac29df144ef75df92f8c0c7554651) diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m index 7fd3d16..f251d23 100644 --- a/hw/xquartz/X11Application.m +++ b/hw/xquartz/X11Application.m @@ -214,9 +214,7 @@ message_kit_thread(SEL selector, NSObject *arg) if (state) { if (bgMouseLocationUpdated) { DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, - bgMouseLocation.x, bgMouseLocation.y, 0.0, - 0.0, - 0.0); + bgMouseLocation.x, bgMouseLocation.y); bgMouseLocationUpdated = FALSE; } DarwinSendDDXEvent(kXquartzActivate, 0); @@ -1501,9 +1499,9 @@ handle_mouse: if ([e isEnteringProximity]) needsProximityIn = YES; else - DarwinSendProximityEvents(darwinTabletCurrent, ProximityOut, - location.x, location.y, pressure, - tilt.x, tilt.y); + DarwinSendTabletEvents(darwinTabletCurrent, ProximityOut, 0, + location.x, location.y, pressure, + tilt.x, tilt.y); return; } @@ -1515,9 +1513,9 @@ handle_mouse: pDev = darwinTabletCurrent; if (needsProximityIn) { - DarwinSendProximityEvents(darwinTabletCurrent, ProximityIn, - location.x, location.y, pressure, - tilt.x, tilt.y); + DarwinSendTabletEvents(darwinTabletCurrent, ProximityIn, 0, + location.x, location.y, pressure, + tilt.x, tilt.y); needsProximityIn = NO; } @@ -1548,14 +1546,20 @@ handle_mouse: if (bgMouseLocationUpdated) { if (!(ev_type == MotionNotify && ev_button == 0)) { - DarwinSendPointerEvents(pDev, MotionNotify, 0, location.x, - location.y, pressure, tilt.x, tilt.y); + DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, + location.x, location.y); } bgMouseLocationUpdated = FALSE; } - DarwinSendPointerEvents(pDev, ev_type, ev_button, location.x, - location.y, pressure, tilt.x, tilt.y); + if (pDev == darwinPointer) { + DarwinSendPointerEvents(pDev, ev_type, ev_button, + location.x, location.y); + } else { + DarwinSendTabletEvents(pDev, ev_type, ev_button, + location.x, location.y, pressure, + tilt.x, tilt.y); + } break; @@ -1579,9 +1583,9 @@ handle_mouse: if ([e isEnteringProximity]) needsProximityIn = YES; else - DarwinSendProximityEvents(darwinTabletCurrent, ProximityOut, - location.x, location.y, pressure, - tilt.x, tilt.y); + DarwinSendTabletEvents(darwinTabletCurrent, ProximityOut, 0, + location.x, location.y, pressure, + tilt.x, tilt.y); break; case NSScrollWheel: @@ -1595,8 +1599,7 @@ handle_mouse: if (!XQuartzServerVisible && noTestExtensions) { bgMouseLocationUpdated = FALSE; DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, - location.x, location.y, pressure, - tilt.x, tilt.y); + location.x, location.y); } #endif #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c index c62dd44..9fc23a3 100644 --- a/hw/xquartz/darwinEvents.c +++ b/hw/xquartz/darwinEvents.c @@ -44,19 +44,20 @@ #include <dix-config.h> #endif -#include <X11/X.h> -#include <X11/Xmd.h> -#include <X11/Xproto.h> -#include "misc.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "inputstr.h" -#include "inpututils.h" -#include "eventstr.h" -#include "mi.h" -#include "scrnintstr.h" -#include "mipointer.h" -#include "os.h" +#include <X11/X.h> +#include <X11/Xmd.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "inputstr.h" +#include "inpututils.h" +#include "eventstr.h" +#include "mi.h" +#include "scrnintstr.h" +#include "mipointer.h" +#include "os.h" +#include "exglobals.h" #include "darwin.h" #include "quartz.h" @@ -442,56 +443,6 @@ DarwinPokeEQ(void) write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte)); } -/* Convert from Appkit pointer input values to X input values: - * Note: pointer_x and pointer_y are relative to the upper-left of primary - * display. - */ -static void -DarwinPrepareValuators(DeviceIntPtr pDev, ValuatorMask *pmask, - ScreenPtr screen, - double pointer_x, double pointer_y, - double pressure, double tilt_x, - double tilt_y) -{ - - valuator_mask_zero(pmask); - - /* Fix offset between darwin and X screens */ - pointer_x -= darwinMainScreenX + screen->x; - pointer_y -= darwinMainScreenY + screen->y; - - if (pointer_x < 0.0) - pointer_x = 0.0; - - if (pointer_y < 0.0) - pointer_y = 0.0; - - if (pDev == darwinPointer) { - valuator_mask_set_double(pmask, 0, pointer_x); - valuator_mask_set_double(pmask, 1, pointer_y); - } - else { - valuator_mask_set_double(pmask, 0, XQUARTZ_VALUATOR_LIMIT * - (pointer_x / - (double)screenInfo.screens[0]->width)); - valuator_mask_set_double(pmask, 1, XQUARTZ_VALUATOR_LIMIT * - (pointer_y / - (double)screenInfo.screens[0]->height)); - valuator_mask_set_double(pmask, 2, XQUARTZ_VALUATOR_LIMIT * pressure); - valuator_mask_set_double(pmask, 3, XQUARTZ_VALUATOR_LIMIT * tilt_x); - valuator_mask_set_double(pmask, 4, XQUARTZ_VALUATOR_LIMIT * tilt_y); - DEBUG_LOG("Pointer (%lf, %lf), Valuators: {%lf,%lf,%lf,%lf,%lf}\n", - pointer_x, pointer_y, - valuator_mask_get_double(pmask, - 0), - valuator_mask_get_double(pmask, 1), - valuator_mask_get_double(pmask, - 2), - valuator_mask_get_double(pmask, 3), - valuator_mask_get_double(pmask, 4)); - } -} - void DarwinInputReleaseButtonsAndKeys(DeviceIntPtr pDev) { @@ -521,27 +472,78 @@ DarwinInputReleaseButtonsAndKeys(DeviceIntPtr pDev) } void +DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button, + double pointer_x, double pointer_y, + double pressure, double tilt_x, + double tilt_y) +{ + ScreenPtr screen; + ValuatorMask valuators; + + if (!darwinEvents) { + DEBUG_LOG("%s called before darwinEvents was initialized\n", + __FUNCTION__); + return; + } + + screen = miPointerGetScreen(pDev); + if (!screen) { + DEBUG_LOG("%s called before screen was initialized\n", + __FUNCTION__); + return; + } -- To UNSUBSCRIBE, email to debian-x-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/e1srbe2-0002fb...@vasks.debian.org