[haiku-development] GLTeapot and R5/Haiku mouse tracking

  • From: Alexandre Deckner <alex@xxxxxxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Fri, 22 Feb 2008 13:27:45 +0100

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

Other related posts: