Hi,i was annoyed by the mouse interaction laggyness in GLTeapot and basically rewrote mouse tracking. It works well, especially on slow hardware and vmware. However, although i find my code simpler and cleaner than the original :-P, it is still a workaround in the sense that there's no problem under R5. As noted recently by Stefano (couldn't find your post back), mouse messages seems to be filtered ahead under R5 (or something like that, app server?). I don't know how many R5 apps suffer from this (netpositive middle button scroll iirc), but that would be great for binary (source even) compatibility. I'll post a ticket if there isn't one already.
In the mean time, what about my happy teapot patch? should i commit it? Regards, Alex
Index: src/apps/glteapot/ObjectView.cpp =================================================================== --- src/apps/glteapot/ObjectView.cpp (revision 24010) +++ src/apps/glteapot/ObjectView.cpp (working copy) @@ -139,6 +139,14 @@ fLastYXRatio(1), fYxRatio(1) { + fTrackingInfo.isTracking = false; + fTrackingInfo.pickedObject = NULL; + fTrackingInfo.buttons = 0; + fTrackingInfo.lastX = 0.0f; + fTrackingInfo.lastY = 0.0f; + fTrackingInfo.lastDx = 0.0f; + fTrackingInfo.lastDy = 0.0f; + fLastObjectDistance = fObjectDistance = depthOfView/8; quittingSem = create_sem(1,"quitting sem"); drawEvent = create_sem(0,"draw event"); @@ -394,100 +402,107 @@ void ObjectView::MouseDown(BPoint p) { - BPoint op = p, np = p; - BRect bounds = Bounds(); - float lastDx = 0,lastDy = 0; - GLObject* o = NULL; - uint32 mods; + GLObject* o = NULL; BMessage *m = Window()->CurrentMessage(); uint32 buttons = m->FindInt32("buttons"); o = ((GLObject*)fObjects.ItemAt(ObjectAtPoint(p))); - long locks = 0; - - while (Window()->IsLocked()) { - locks++; - Window()->Unlock(); - } + if (o != NULL){ + if (buttons == B_PRIMARY_MOUSE_BUTTON || buttons == B_SECONDARY_MOUSE_BUTTON) { + fTrackingInfo.pickedObject = o; + fTrackingInfo.buttons = buttons; + fTrackingInfo.isTracking = true; + fTrackingInfo.lastX = p.x; + fTrackingInfo.lastY = p.y; + fTrackingInfo.lastDx = 0.0f; + fTrackingInfo.lastDy = 0.0f; + fTrackingInfo.pickedObject->spinX = 0.0f; + fTrackingInfo.pickedObject->spinY = 0.0f; + + SetMouseEventMask(B_POINTER_EVENTS, + B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY); + } else { + BPoint point = p; + ConvertToScreen(&point); + o->MenuInvoked(point); + } + } +} - if (buttons == B_SECONDARY_MOUSE_BUTTON) { - if (o) { - while (buttons) { - lastDx = np.x - op.x; - lastDy = np.y - op.y; - - if (lastDx || lastDy) { - float xinc = (lastDx * 2 * displayScale / bounds.Width()); - float yinc = (-lastDy * 2 * displayScale / bounds.Height()); - float zinc = 0; - - if (fPersp) { - zinc = yinc * (o->z / displayScale); - xinc *= -(o->z * 4 / zRatio); - yinc *= -(o->z * 4 / zRatio); - } - o->x += xinc; - mods = modifiers(); - if (mods & B_SHIFT_KEY) - o->z += zinc; - else - o->y += yinc; - op = np; - fForceRedraw = true; - setEvent(drawEvent); - } - snooze(25000); - - Window()->Lock(); - GetMouse(&np, &buttons, true); - Window()->Unlock(); - } +void +ObjectView::MouseUp(BPoint point) +{ + if (fTrackingInfo.isTracking) { + + //spin the teapot on release, TODO: use a marching sum and divide by time + if (fTrackingInfo.buttons == B_PRIMARY_MOUSE_BUTTON + && fTrackingInfo.pickedObject != NULL + && (fabs(fTrackingInfo.lastDx) > 1.0f + || fabs(fTrackingInfo.lastDy) > 1.0f) ) { + + fTrackingInfo.pickedObject->spinX = 0.5f * fTrackingInfo.lastDy; + fTrackingInfo.pickedObject->spinY = 0.5f * fTrackingInfo.lastDx; + + setEvent(drawEvent); } - } else if (buttons == B_PRIMARY_MOUSE_BUTTON) { - float llx = 0, lly = 0; - lastDx = lastDy = 0; - if (o) { - o->spinX = 0; - o->spinY = 0; - while (buttons) { - llx = lastDx; - lly = lastDy; - lastDx = np.x - op.x; - lastDy = np.y - op.y; - - if (lastDx || lastDy) { - o->rotY += lastDx; - o->rotX += lastDy; - op = np; - setEvent(drawEvent); - } + //stop tracking + fTrackingInfo.isTracking = false; + fTrackingInfo.buttons = 0; + fTrackingInfo.pickedObject = NULL; + fTrackingInfo.lastX = 0.0f; + fTrackingInfo.lastY = 0.0f; + fTrackingInfo.lastDx = 0.0f; + fTrackingInfo.lastDy = 0.0f; + } +} - snooze(25000); - Window()->Lock(); - GetMouse(&np, &buttons, true); - Window()->Unlock(); +void +ObjectView::MouseMoved(BPoint point, uint32 transit, const BMessage *msg) +{ + if (fTrackingInfo.isTracking && fTrackingInfo.pickedObject != NULL) { + + float dx = point.x - fTrackingInfo.lastX; + float dy = point.y - fTrackingInfo.lastY; + fTrackingInfo.lastX = point.x; + fTrackingInfo.lastY = point.y; + + if (fTrackingInfo.buttons == B_PRIMARY_MOUSE_BUTTON) { + + fTrackingInfo.pickedObject->spinX = 0; + fTrackingInfo.pickedObject->spinY = 0; + fTrackingInfo.pickedObject->rotY += dx; + fTrackingInfo.pickedObject->rotX += dy; + fTrackingInfo.lastDx = dx; + fTrackingInfo.lastDy = dy; + + setEvent(drawEvent); + + } else if (fTrackingInfo.buttons == B_SECONDARY_MOUSE_BUTTON) { + + float xinc = (dx * 2 * displayScale / Bounds().Width()); + float yinc = (-dy * 2 * displayScale / Bounds().Height()); + float zinc = 0; + + if (fPersp) { + zinc = yinc * (fTrackingInfo.pickedObject->z / displayScale); + xinc *= -(fTrackingInfo.pickedObject->z * 4 / zRatio); + yinc *= -(fTrackingInfo.pickedObject->z * 4 / zRatio); } - o->spinY = lastDx + llx; - o->spinX = lastDy + lly; - } - } else { - if (o) { - BPoint point = p; - Window()->Lock(); - ConvertToScreen(&point); - Window()->Unlock(); - o->MenuInvoked(point); - } - } - - while (locks--) - Window()->Lock(); - - setEvent(drawEvent); + + fTrackingInfo.pickedObject->x += xinc; + if (modifiers() & B_SHIFT_KEY) + fTrackingInfo.pickedObject->z += zinc; + else + fTrackingInfo.pickedObject->y += yinc; + + fForceRedraw = true; + setEvent(drawEvent); + } + } } Index: src/apps/glteapot/ObjectView.h =================================================================== --- src/apps/glteapot/ObjectView.h (revision 24010) +++ src/apps/glteapot/ObjectView.h (working copy) @@ -33,7 +33,18 @@ #define HISTSIZE 10 class ResScroll; +class GLObject; +struct TrackingInfo { + float lastX; + float lastY; + float lastDx; + float lastDy; + bool isTracking; + GLObject *pickedObject; + uint32 buttons; +}; + class ObjectView : public BGLView { public: ObjectView(BRect r, char* name, ulong resizingMode, @@ -41,6 +52,9 @@ ~ObjectView(); virtual void MouseDown(BPoint p); + virtual void MouseUp(BPoint p); + virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *msg); + virtual void MessageReceived(BMessage* msg); virtual void AttachedToWindow(); virtual void DetachedFromWindow(); @@ -69,6 +83,7 @@ bool fLastFog, fFog, fForceRedraw; float fLastYXRatio, fYxRatio, fFpsHistory[HISTSIZE]; float fObjectDistance,fLastObjectDistance; + TrackingInfo fTrackingInfo; }; #endif // OBJECT_VIEW_H