diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-01-16 22:05:17 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-01-16 22:05:17 +0400 |
commit | cda2b7db0fe904538ffa42ae4f63527f3defc3be (patch) | |
tree | 6d2cb917c711bfb91345d9c454f5a76b352ab3a8 | |
parent | 44115a74159651902ad9c88d9f5dd577aa97e3fd (diff) |
fix for glitch in X11 with tablets.
Notices this while using continuous-grab, since this is disabled when the tablet is being used.
Quite often I would use the tablet then drag a button with the mouse but blender would still have the tablet enabled.
This error would cause other parts of blender to behave incorrectly too since wmEvents would have wmTabletData set, operators check for this in some cases.
The problem was blender didn't reliably get ProximityOut events, eg:
moving the cursor outside the window with the tablet, then back over the window with the mouse -
meant blender didn't get a 'ProximityOut' event and would keep the active stylus value set.
For now, when the processing events and the active stylus is set, run a check that the tablet is still in proximity.
-rw-r--r-- | intern/ghost/intern/GHOST_SystemX11.cpp | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index b7715de665d..f5c31c93335 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -518,6 +518,40 @@ static void setTabletMode(GHOST_SystemX11 *system, GHOST_WindowX11 *window, XID } #endif /* WITH_X11_XINPUT */ +#ifdef WITH_X11_XINPUT +static bool checkTabletProximity(Display *display, XDevice *device) +{ + /* see: state.c from xinput, to get more data out of the device */ + XDeviceState *state; + + state = XQueryDeviceState(display, device); + + if (state) { + XInputClass *cls = state->data; + // printf("%d class%s :\n", state->num_classes, + // (state->num_classes > 1) ? "es" : ""); + for(int loop=0; loop < state->num_classes; loop++) { + switch(cls->c_class) { + case ValuatorClass: + XValuatorState *val_state = (XValuatorState *) cls; + // printf("ValuatorClass Mode=%s Proximity=%s\n", + // val_state->mode & 1 ? "Absolute" : "Relative", + // val_state->mode & 2 ? "Out" : "In"); + + if ((val_state->mode & 2) == 0) { + XFreeDeviceState(state); + return true; + } + break; + } + cls = (XInputClass *) ((char *) cls + cls->length); + } + XFreeDeviceState(state); + } + return false; +} +#endif /* WITH_X11_XINPUT */ + void GHOST_SystemX11::processEvent(XEvent *xe) { @@ -527,7 +561,23 @@ GHOST_SystemX11::processEvent(XEvent *xe) if (!window) { return; } - + +#ifdef WITH_X11_XINPUT + /* Proximity-Out Events are not reliable, if the tablet is active - check on each event + * this adds a little overhead but only while the tablet is in use. + * in the futire we could have a ghost call window->CheckTabletProximity() + * but for now enough parts of the code are checking 'Active' + * - campbell */ + if (window->GetTabletData()->Active != GHOST_kTabletModeNone) { + if (checkTabletProximity(xe->xany.display, m_xtablet.StylusDevice) == false && + checkTabletProximity(xe->xany.display, m_xtablet.EraserDevice) == false) + { + // printf("proximity disable\n"); + window->GetTabletData()->Active = GHOST_kTabletModeNone; + } + } +#endif /* WITH_X11_XINPUT */ + switch (xe->type) { case Expose: { |