[haiku-commits] r41892 - in haiku/trunk: headers/private/shared src/kits/shared src/kits/tracker

  • From: alex@xxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 3 Jun 2011 23:12:14 +0200 (CEST)

Author: aldeck
Date: 2011-06-03 23:12:14 +0200 (Fri, 03 Jun 2011)
New Revision: 41892
Changeset: https://dev.haiku-os.org/changeset/41892
Ticket: https://dev.haiku-os.org/ticket/880
Ticket: https://dev.haiku-os.org/ticket/7241

Added:
   haiku/trunk/headers/private/shared/LongAndDragTrackingFilter.h
   haiku/trunk/src/kits/shared/LongAndDragTrackingFilter.cpp
Modified:
   haiku/trunk/src/kits/shared/Jamfile
   haiku/trunk/src/kits/tracker/PoseView.cpp
   haiku/trunk/src/kits/tracker/PoseView.h
Log:
* Finally rewrote the filthy, busy-looping, mouse tracking in Tracker. 
The new asynchronous tracking doesn't lock the view and makes desktop 
replicants happy while clicking and dragging around. Fixes #880, #7241 
and certainly other tickets, that i will revisit, about refresh locks 
on the desktop or mouse related bugs. Based on a reusable MessageFilter and the 
recent B_MOUSE_IDLE message. Some parts are ported from the old code
and could use further simplification.

There should be no intentional user fonctional change, except: 
- slightly bigger threshold radius, shorter duration thresholds
 (= 1.0 x the system-wide doubleclick setting)
- not reimplemented: quickening threshold when holding shift while dragging
 a pose over a destination pose.

Some parts are ported from the old code and could use further simplification.
There is one known minor regression with autoscrolling while 
rect-selecting but that will be better fixed with some changes to the 
autoscroll code. Will address that ASAP. As for the unknown regressions, 
please test :)


Added: haiku/trunk/headers/private/shared/LongAndDragTrackingFilter.h
===================================================================
--- haiku/trunk/headers/private/shared/LongAndDragTrackingFilter.h              
                (rev 0)
+++ haiku/trunk/headers/private/shared/LongAndDragTrackingFilter.h      
2011-06-03 21:12:14 UTC (rev 41892)
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009, Alexandre Deckner, alex@xxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef LONG_AND_DRAG_TRACKING_FILTER_H
+#define LONG_AND_DRAG_TRACKING_FILTER_H
+
+
+#include <MessageFilter.h>
+#include <Point.h>
+
+
+class BHandler;
+class BMessageRunner;
+
+
+namespace BPrivate {
+
+class LongAndDragTrackingFilter : public BMessageFilter {
+public:
+                                                               
LongAndDragTrackingFilter(
+                                                                       uint32 
longMessageWhat,
+                                                                       uint32 
dragMessageWhat,
+                                                                       float 
radiusThreshold = 4.0f,
+                                                                       
bigtime_t durationThreshold = 0);
+                                                               
~LongAndDragTrackingFilter();
+
+                       filter_result           Filter(BMessage* message, 
BHandler** target);
+
+private:
+                       void                            _StopTracking();
+
+                       uint32                          fLongMessageWhat;
+                       uint32                          fDragMessageWhat;
+                       BMessageRunner*         fMessageRunner;
+                       BPoint                          fClickPoint;
+                       uint32                          fClickButtons;
+                       float                           fSquaredRadiusThreshold;
+                       bigtime_t                       fDurationThreshold;
+};
+
+}      // namespace BPrivate
+
+using BPrivate::LongAndDragTrackingFilter;
+
+#endif // LONG_AND_DRAG_TRACKING_FILTER_H
+

Modified: haiku/trunk/src/kits/shared/Jamfile
===================================================================
--- haiku/trunk/src/kits/shared/Jamfile 2011-06-03 21:11:38 UTC (rev 41891)
+++ haiku/trunk/src/kits/shared/Jamfile 2011-06-03 21:12:14 UTC (rev 41892)
@@ -23,6 +23,7 @@
        IconButton.cpp
        IconView.cpp
        Keymap.cpp
+       LongAndDragTrackingFilter.cpp
        NaturalCompare.cpp
        QueryFile.cpp
        RWLockManager.cpp

Added: haiku/trunk/src/kits/shared/LongAndDragTrackingFilter.cpp
===================================================================
--- haiku/trunk/src/kits/shared/LongAndDragTrackingFilter.cpp                   
        (rev 0)
+++ haiku/trunk/src/kits/shared/LongAndDragTrackingFilter.cpp   2011-06-03 
21:12:14 UTC (rev 41892)
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2011, Alexandre Deckner, alex@xxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+/*!
+       \class LongAndDragTrackingFilter
+       \brief A simple long mouse down and drag detection filter
+       * 
+       * A simple mouse filter that detects long clicks and pointer drags.
+       * A long click message is sent when the mouse button is kept down
+       * for a duration longer than a given threshold while the pointer stays
+       * within the limits of a given threshold radius.
+       * A drag message is triggered if the mouse goes further than the
+       * threshold radius before the duration threshold elapsed.
+       *
+       * The messages contain the pointer position and the buttons state at
+       * the moment of the click. The drag message is ready to use with the
+       * be/haiku drag and drop API cf. comment in code.
+       *
+       * Note: for simplicity and current needs (Tracker), only the left mouse
+       * button is tracked. 
+       *
+*/
+
+
+#include <LongAndDragTrackingFilter.h>
+
+#include <Message.h>
+#include <Messenger.h>
+#include <MessageRunner.h>
+#include <View.h>
+
+#include <new>
+
+
+LongAndDragTrackingFilter::LongAndDragTrackingFilter(uint32 longMessageWhat,
+       uint32 dragMessageWhat, float radiusThreshold,
+       bigtime_t durationThreshold)
+       :
+       BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
+       fLongMessageWhat(longMessageWhat),
+       fDragMessageWhat(dragMessageWhat),
+       fMessageRunner(NULL),
+       fClickButtons(0),
+       fSquaredRadiusThreshold(radiusThreshold * radiusThreshold)
+{
+       if (durationThreshold == 0) {
+               get_click_speed(&fDurationThreshold);
+                       // use system's doubleClickSpeed as default threshold
+       }
+}
+
+
+LongAndDragTrackingFilter::~LongAndDragTrackingFilter()
+{
+       delete fMessageRunner;
+}
+
+
+void
+LongAndDragTrackingFilter::_StopTracking()
+{
+       delete fMessageRunner;
+       fMessageRunner = NULL;
+}
+
+
+filter_result
+LongAndDragTrackingFilter::Filter(BMessage* message, BHandler** target)
+{
+       if (*target == NULL)
+               return B_DISPATCH_MESSAGE;
+
+       switch (message->what) {
+               case B_MOUSE_DOWN:
+
+                       message->FindInt32("buttons", (int32*)&fClickButtons);
+
+                       if ((fClickButtons & B_PRIMARY_MOUSE_BUTTON)
+                               == B_PRIMARY_MOUSE_BUTTON) {
+
+                               BView* targetView = 
dynamic_cast<BView*>(*target);
+                               if (targetView != NULL)
+                                       
targetView->SetMouseEventMask(B_POINTER_EVENTS);
+
+                               message->FindPoint("where", &fClickPoint);
+                               BMessage message(fLongMessageWhat);
+                               message.AddPoint("where", fClickPoint);
+                               message.AddInt32("buttons", fClickButtons);
+
+                               delete fMessageRunner;
+                               fMessageRunner = new (std::nothrow) 
BMessageRunner(
+                                       BMessenger(*target), &message, 
fDurationThreshold, 1);
+                       }
+                       return B_DISPATCH_MESSAGE;
+
+               case B_MOUSE_UP:
+                       _StopTracking();
+                       return B_DISPATCH_MESSAGE;
+
+               case B_MOUSE_MOVED:
+               {
+                       if (fMessageRunner != NULL) { 
+                               BPoint where;
+                               message->FindPoint("be:view_where", &where);
+                       
+                               BPoint delta(fClickPoint - where);
+                               float squaredDelta = (delta.x * delta.x) + 
(delta.y * delta.y);
+
+                               if (squaredDelta >= fSquaredRadiusThreshold) {
+                                       BMessage dragMessage(fDragMessageWhat);
+                                       dragMessage.AddPoint("be:view_where", 
fClickPoint);
+                                               // name it "be:view_where" 
since BView::DragMessage
+                                               // positions the dragging 
frame/bitmap by retrieving
+                                               // the current message and 
reading that field
+                                       dragMessage.AddInt32("buttons", 
fClickButtons);
+                                       BMessenger messenger(*target);
+                                       messenger.SendMessage(&dragMessage);
+
+                                       _StopTracking();
+                               }
+                       }
+                       return B_DISPATCH_MESSAGE;
+               }
+
+               default:
+                       if (message->what == fLongMessageWhat) {
+                               _StopTracking();
+                               return B_DISPATCH_MESSAGE;
+                       }
+                       break;
+       }
+
+       return B_DISPATCH_MESSAGE;
+}

Modified: haiku/trunk/src/kits/tracker/PoseView.cpp
===================================================================
--- haiku/trunk/src/kits/tracker/PoseView.cpp   2011-06-03 21:11:38 UTC (rev 
41891)
+++ haiku/trunk/src/kits/tracker/PoseView.cpp   2011-06-03 21:12:14 UTC (rev 
41892)
@@ -58,6 +58,7 @@
 #include <Query.h>
 #include <List.h>
 #include <Locale.h>
+#include <LongAndDragTrackingFilter.h>
 #include <MenuItem.h>
 #include <NodeMonitor.h>
 #include <Path.h>
@@ -113,6 +114,8 @@
 const uint32 kAddNewPoses = 'Tanp';
 const uint32 kAddPosesCompleted = 'Tapc';
 const int32 kMaxAddPosesChunk = 50;
+const uint32 kMsgMouseDragged = 'Mdrg';
+const uint32 kMsgMouseLongDown = 'Mold';
 
 
 namespace BPrivate {
@@ -922,6 +925,8 @@
        AddFilter(new ShortcutFilter(B_ESCAPE, B_SHIFT_KEY, 
kCancelSelectionToClipboard, this));
                // Escape + SHIFT will remove current selection from clipboard, 
or all poses from current folder if 0 selected
 
+       AddFilter(new LongAndDragTrackingFilter(kMsgMouseLongDown, 
kMsgMouseDragged));
+
        fLastLeftTop = LeftTop();
        BFont font(be_plain_font);
        font.SetSpacing(B_BITMAP_SPACING);
@@ -2154,6 +2159,18 @@
                case kMiniIconMode:
                        SetViewMode(message->what);
                        break;
+               
+               case kMsgMouseDragged:
+                       MouseDragged(message);
+                       break;
+                       
+               case kMsgMouseLongDown:
+                       MouseLongDown(message);
+                       break;
+                       
+               case B_MOUSE_IDLE:
+                       MouseIdle(message);                     
+                       break;
 
                case B_SELECT_ALL:
                {
@@ -6545,10 +6562,237 @@
 
 
 void
-BPoseView::MouseDown(BPoint where)
+BPoseView::_BeginSelectionRect(const BPoint& point, bool shouldExtend)
 {
-       // TODO: add asynch mouse tracking
+       // set initial empty selection rectangle
+       fSelectionRectInfo.rect = BRect(point, point - BPoint(1, 1));
 
+       if (!fTransparentSelection) {
+               SetDrawingMode(B_OP_INVERT);
+               StrokeRect(fSelectionRectInfo.rect, B_MIXED_COLORS);
+               SetDrawingMode(B_OP_OVER);
+       }
+
+       fSelectionRectInfo.lastRect = fSelectionRectInfo.rect;
+       fSelectionRectInfo.selection = new BList;
+       fSelectionRectInfo.startPoint = point;
+       fSelectionRectInfo.lastPoint = point;
+       fSelectionRectInfo.isDragging = true;
+}
+
+
+static void
+AddIfPoseSelected(BPose *pose, PoseList *list)
+{
+       if (pose->IsSelected())
+               list->AddItem(pose);
+}
+
+
+void
+BPoseView::_UpdateSelectionRect(const BPoint& point)
+{
+       if (point != fSelectionRectInfo.lastPoint) {
+
+               fSelectionRectInfo.lastPoint = point;
+
+               // erase last rect
+               if (!fTransparentSelection) {
+                       SetDrawingMode(B_OP_INVERT);
+                       StrokeRect(fSelectionRectInfo.rect, B_MIXED_COLORS);
+                       SetDrawingMode(B_OP_OVER);
+               }
+
+               fSelectionRectInfo.rect.top = std::min(point.y,
+                       fSelectionRectInfo.startPoint.y);
+               fSelectionRectInfo.rect.left = std::min(point.x,
+                       fSelectionRectInfo.startPoint.x);
+               fSelectionRectInfo.rect.bottom = std::max(point.y,
+                       fSelectionRectInfo.startPoint.y);
+               fSelectionRectInfo.rect.right = std::max(point.x,
+                       fSelectionRectInfo.startPoint.x);
+
+               fIsDrawingSelectionRect = true;
+
+               CheckAutoScroll(point, true, true);
+
+               // use current selection rectangle to scan poses
+               if (ViewMode() == kListMode) {
+                       SelectPosesListMode(fSelectionRectInfo.rect,
+                               &fSelectionRectInfo.selection);
+               } else {
+                       SelectPosesIconMode(fSelectionRectInfo.rect,
+                               &fSelectionRectInfo.selection);
+               }
+
+               Window()->UpdateIfNeeded();
+
+               // draw new rect
+               if (!fTransparentSelection) {
+                       SetDrawingMode(B_OP_INVERT);
+                       StrokeRect(fSelectionRectInfo.rect, B_MIXED_COLORS);
+                       SetDrawingMode(B_OP_OVER);
+               } else {
+                       BRegion updateRegion1;
+                       BRegion updateRegion2;
+
+                       bool sameWidth = fSelectionRectInfo.rect.Width()
+                               == fSelectionRectInfo.lastRect.Width();
+                       bool sameHeight = fSelectionRectInfo.rect.Height()
+                               == fSelectionRectInfo.lastRect.Height();
+
+                       updateRegion1.Include(fSelectionRectInfo.rect);
+                       
updateRegion1.Exclude(fSelectionRectInfo.lastRect.InsetByCopy(
+                               sameWidth ? 0 : 1, sameHeight ? 0 : 1));
+                       updateRegion2.Include(fSelectionRectInfo.lastRect);
+                       
updateRegion2.Exclude(fSelectionRectInfo.rect.InsetByCopy(
+                               sameWidth ? 0 : 1, sameHeight ? 0 : 1));
+                       updateRegion1.Include(&updateRegion2);
+                       BRect unionRect = fSelectionRectInfo.rect
+                               & fSelectionRectInfo.lastRect;
+                       updateRegion1.Exclude(unionRect
+                               & BRect(-2000, fSelectionRectInfo.startPoint.y, 
2000,
+                               fSelectionRectInfo.startPoint.y));
+                       updateRegion1.Exclude(unionRect
+                               & BRect(fSelectionRectInfo.startPoint.x, -2000,
+                               fSelectionRectInfo.startPoint.x, 2000));
+
+                       fSelectionRectInfo.lastRect = fSelectionRectInfo.rect;
+
+                       Invalidate(&updateRegion1);
+                       Window()->UpdateIfNeeded();
+               }
+               Flush();
+       }
+}
+
+
+void
+BPoseView::_EndSelectionRect()
+{
+       delete fSelectionRectInfo.selection;
+       fSelectionRectInfo.selection = NULL;
+
+       fSelectionRectInfo.isDragging = false;
+       fIsDrawingSelectionRect = false; // TODO: remove BPose dependency?
+
+       // do final erase of selection rect
+       if (!fTransparentSelection) {
+               SetDrawingMode(B_OP_INVERT);
+               StrokeRect(fSelectionRectInfo.rect, B_MIXED_COLORS);
+               SetDrawingMode(B_OP_COPY);
+       } else {
+               Invalidate(fSelectionRectInfo.rect);
+               fSelectionRectInfo.rect.Set(0, 0, -1, -1);
+               Window()->UpdateIfNeeded();
+       }
+
+       // we now need to update the pose view's selection list by clearing it
+       // and then polling each pose for selection state and rebuilding list
+       fSelectionList->MakeEmpty();
+       fMimeTypesInSelectionCache.MakeEmpty();
+
+       EachListItem(fPoseList, AddIfPoseSelected, fSelectionList);
+
+       // and now make sure that the pivot point is in sync
+       if (fSelectionPivotPose && 
!fSelectionList->HasItem(fSelectionPivotPose))
+               fSelectionPivotPose = NULL;
+       if (fRealPivotPose && !fSelectionList->HasItem(fRealPivotPose))
+               fRealPivotPose = NULL;
+}
+
+
+void
+BPoseView::MouseMoved(BPoint mouseLoc, uint32 moveCode, const BMessage 
*message)
+{
+       if (fSelectionRectInfo.isDragging)
+               _UpdateSelectionRect(mouseLoc);
+       
+       if (!fDropEnabled || !message)
+               return;
+
+       BContainerWindow* window = ContainerWindow();
+       if (!window)
+               return;
+
+       switch (moveCode) {
+               case B_INSIDE_VIEW:
+               case B_ENTERED_VIEW:
+                       UpdateDropTarget(mouseLoc, message, 
window->ContextMenu());
+                       if (fAutoScrollState == kAutoScrollOff) {
+                               // turn on auto scrolling if it's not yet on
+                               fAutoScrollState = kWaitForTransition;
+                               window->SetPulseRate(100000);
+                       }
+                       break;
+
+               case B_EXITED_VIEW:
+                       // reset cursor in case we set it to the copy cursor
+                       // in UpdateDropTarget
+                       SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
+                       fCursorCheck = false;
+                       // TODO: autoscroll here
+                       if (!window->ContextMenu()) {
+                               HiliteDropTarget(false);
+                               fDropTarget = NULL;
+                       }
+                       break;
+       }       
+}
+
+
+void
+BPoseView::MouseDragged(const BMessage *message)
+{
+       BPoint where;
+       if (message->FindPoint("be:view_where", &where) != B_OK)
+               return;
+
+       bool extendSelection = (modifiers() & B_COMMAND_KEY) && 
fMultipleSelection;
+
+       int32 index;
+       BPose* pose = FindPose(where, &index);
+       if (pose != NULL)
+               DragSelectedPoses(pose, where);
+       else
+               _BeginSelectionRect(where, extendSelection);    
+}
+
+
+void
+BPoseView::MouseLongDown(const BMessage *message)
+{
+       BPoint where;
+       if (message->FindPoint("where", &where) != B_OK)
+               return;
+
+       ShowContextMenu(where);
+}
+
+
+void
+BPoseView::MouseIdle(const BMessage *message)
+{
+       BPoint where;
+       uint32 buttons = 0;
+       GetMouse(&where, &buttons);
+       BContainerWindow* window = ContainerWindow();
+
+       if (buttons == 0 || window == NULL)
+               return;
+                       
+       if (fDropTarget != NULL) {
+               window->DragStart(message);
+               FrameForPose(fDropTarget, true, &fStartFrame);
+               ShowContextMenu(where);
+       } else
+               window->Activate();
+}
+
+
+void
+BPoseView::MouseDown(BPoint where)
+{
        // handle disposing of drag data lazily
        DragStop();
        BContainerWindow *window = ContainerWindow();
@@ -6572,7 +6816,6 @@
        if ((buttons & B_SECONDARY_MOUSE_BUTTON) == 0)
                showContext = (modifs & B_CONTROL_KEY) != 0;
 
-       // if a pose was hit, delay context menu for a bit to see if user 
dragged
        if (showContext) {
                int32 index;
                BPose *pose = FindPose(where, &index);
@@ -6586,24 +6829,7 @@
                        fSelectionList->AddItem(pose);
                        DrawPose(pose, index, false);
                }
-
-               bigtime_t clickTime = system_time();
-               BPoint loc;
-               GetMouse(&loc, &buttons);
-               for (;;) {
-                       if (fabs(loc.x - where.x) > 4 || fabs(loc.y - where.y) 
> 4)
-                               // moved the mouse, cancel showing the context 
menu
-                               break;
-
-                       if (!buttons || (system_time() - clickTime) > 200000) {
-                               // let go of button or pressing for a while, 
show menu now
-                               ShowContextMenu(where);
-                               return;
-                       }
-
-                       snooze(10000);
-                       GetMouse(&loc, &buttons);
-               }
+               ShowContextMenu(where);
        }
 
        bool extendSelection = (modifs & B_COMMAND_KEY) && fMultipleSelection;
@@ -6616,26 +6842,10 @@
        if (pose) {
                AddRemoveSelectionRange(where, extendSelection, pose);
 
-               switch (WaitForMouseUpOrDrag(where)) {
-                       case kWasDragged:
-                               DragSelectedPoses(pose, where);
-                               break;
-
-                       case kNotDragged:
-                               if (!extendSelection && WasDoubleClick(pose, 
where)) {
-                                       // special handling for Path field 
double-clicks
-                                       if (!WasClickInPath(pose, index, where))
-                                               OpenSelection(pose, &index);
-
-                               } else if (fAllowPoseEditing)
-                                       // mouse is up but no drag or 
double-click occurred
-                                       pose->MouseUp(BPoint(0, index * 
fListElemHeight), this, where, index);
-
-                               break;
-
-                       default:
-                               // this is the CONTEXT_MENU case
-                               break;
+               if (!extendSelection && WasDoubleClick(pose, where)) {
+                       // special handling for Path field double-clicks
+                       if (!WasClickInPath(pose, index, where))
+                               OpenSelection(pose, &index);
                }
        } else {
                // click was not in any pose
@@ -6643,7 +6853,10 @@
 
                window->Activate();
                window->UpdateIfNeeded();
-               DragSelectionRect(where, extendSelection);
+               
+               // only clear selection if we are not extending it
+               if (!extendSelection || !fSelectionRectEnabled || 
!fMultipleSelection)
+                       ClearSelection();
        }
 
        if (fSelectionChangedHook)
@@ -6651,6 +6864,19 @@
 }
 
 
+void
+BPoseView::MouseUp(BPoint where)
+{
+       if (fSelectionRectInfo.isDragging)
+               _EndSelectionRect();
+
+       int32 index;
+       BPose* pose = FindPose(where, &index);
+       if (pose != NULL && fAllowPoseEditing)
+               pose->MouseUp(BPoint(0, index * fListElemHeight), this, where, 
index);
+}
+
+
 bool
 BPoseView::WasClickInPath(const BPose *pose, int32 index, BPoint mouseLoc) 
const
 {
@@ -6971,149 +7197,8 @@
 }
 
 
-static void
-AddIfPoseSelected(BPose *pose, PoseList *list)
-{
-       if (pose->IsSelected())
-               list->AddItem(pose);
-}
-
-
-void
-BPoseView::DragSelectionRect(BPoint startPoint, bool shouldExtend)
-{
-       // only clear selection if we are not extending it
-       if (!shouldExtend)
-               ClearSelection();
-
-       if (WaitForMouseUpOrDrag(startPoint) != kWasDragged) {
-               if (!shouldExtend)
-                       ClearSelection();
-               return;
-       }
-
-       if (!fSelectionRectEnabled || !fMultipleSelection) {
-               ClearSelection();
-               return;
-       }
-
-       // clearing the selection could take a while so poll the mouse again
-       BPoint newMousePoint;
-       uint32 button;
-       GetMouse(&newMousePoint, &button);
-
-       // draw initial empty selection rectangle
-       BRect lastSelectionRect;
-       fSelectionRect = lastSelectionRect = BRect(startPoint, startPoint - 
BPoint(1, 1));
-
-       if (!fTransparentSelection) {
-               SetDrawingMode(B_OP_INVERT);
-               StrokeRect(fSelectionRect, B_MIXED_COLORS);
-               SetDrawingMode(B_OP_OVER);
-       }
-
-       BList *selectionList = new BList;
-
-       BPoint oldMousePoint(startPoint);
-       while (button) {
-               GetMouse(&newMousePoint, &button, false);
-
-               if (newMousePoint != oldMousePoint) {
-                       oldMousePoint = newMousePoint;
-                       BRect oldRect = fSelectionRect;
-                       fSelectionRect.top = std::min(newMousePoint.y, 
startPoint.y);
-                       fSelectionRect.left = std::min(newMousePoint.x, 
startPoint.x);
-                       fSelectionRect.bottom = std::max(newMousePoint.y, 
startPoint.y);
-                       fSelectionRect.right = std::max(newMousePoint.x, 
startPoint.x);
-
-                       // erase old rect
-                       if (!fTransparentSelection) {
-                               SetDrawingMode(B_OP_INVERT);
-                               StrokeRect(oldRect, B_MIXED_COLORS);
-                               SetDrawingMode(B_OP_OVER);
-                       }
-
-                       fIsDrawingSelectionRect = true;
-
-                       CheckAutoScroll(newMousePoint, true, true);
-
-                       // use current selection rectangle to scan poses
-                       if (ViewMode() == kListMode)
-                               SelectPosesListMode(fSelectionRect, 
&selectionList);
-                       else
-                               SelectPosesIconMode(fSelectionRect, 
&selectionList);
-
-                       Window()->UpdateIfNeeded();
-
-                       // draw new selected rect
-                       if (!fTransparentSelection) {
-                               SetDrawingMode(B_OP_INVERT);
-                               StrokeRect(fSelectionRect, B_MIXED_COLORS);
-                               SetDrawingMode(B_OP_OVER);
-                       } else {
-                               BRegion updateRegion1;
-                               BRegion updateRegion2;
-
-                               bool sameWidth = fSelectionRect.Width() == 
lastSelectionRect.Width();
-                               bool sameHeight = fSelectionRect.Height() == 
lastSelectionRect.Height();
-
-                               updateRegion1.Include(fSelectionRect);
-                               
updateRegion1.Exclude(lastSelectionRect.InsetByCopy(
-                                       sameWidth ? 0 : 1, sameHeight ? 0 : 1));
-                               updateRegion2.Include(lastSelectionRect);
-                               
updateRegion2.Exclude(fSelectionRect.InsetByCopy(
-                                       sameWidth ? 0 : 1, sameHeight ? 0 : 1));
-                               updateRegion1.Include(&updateRegion2);
-                               BRect unionRect = fSelectionRect & 
lastSelectionRect;
-                               updateRegion1.Exclude(unionRect
-                                       & BRect(-2000, startPoint.y, 2000, 
startPoint.y));
-                               updateRegion1.Exclude(unionRect
-                                       & BRect(startPoint.x, -2000, 
startPoint.x, 2000));
-
-                               lastSelectionRect = fSelectionRect;
-
-                               Invalidate(&updateRegion1);
-                               Window()->UpdateIfNeeded();
-                       }
-
-                       Flush();
-               }
-
-               snooze(20000);
-       }
-
-       delete selectionList;
-
-       fIsDrawingSelectionRect = false;
-
-       // do final erase of selection rect
-       if (!fTransparentSelection) {
-               SetDrawingMode(B_OP_INVERT);
-               StrokeRect(fSelectionRect, B_MIXED_COLORS);
-               SetDrawingMode(B_OP_COPY);
-       } else {
-               Invalidate(fSelectionRect);
-               fSelectionRect.Set(0, 0, -1, -1);
-               Window()->UpdateIfNeeded();
-       }
-
-       // we now need to update the pose view's selection list by clearing it
-       // and then polling each pose for selection state and rebuilding list
-       fSelectionList->MakeEmpty();
-       fMimeTypesInSelectionCache.MakeEmpty();
-
-       EachListItem(fPoseList, AddIfPoseSelected, fSelectionList);
-
-       // and now make sure that the pivot point is in sync
-       if (fSelectionPivotPose && 
!fSelectionList->HasItem(fSelectionPivotPose))
-               fSelectionPivotPose = NULL;
-       if (fRealPivotPose && !fSelectionList->HasItem(fRealPivotPose))
-               fRealPivotPose = NULL;
-}
-
 // TODO: SelectPosesListMode and SelectPosesIconMode are terrible and share
 // most code
-
 void
 BPoseView::SelectPosesListMode(BRect selectionRect, BList **oldList)
 {
@@ -7347,41 +7432,6 @@
 }
 
 
-int32
-BPoseView::WaitForMouseUpOrDrag(BPoint start)
-{
-       bigtime_t start_time = system_time();
-       bigtime_t doubleClickSpeed;
-       get_click_speed(&doubleClickSpeed);
-
-       // use double the doubleClickSpeed as a treshold
-       doubleClickSpeed *= 2;
-
-       // loop until mouse has been dragged at least 2 pixels
-       uint32 button;
-       BPoint loc;
-       GetMouse(&loc, &button, false);
-
-       while (button) {
-               GetMouse(&loc, &button, false);
-               if (fabs(loc.x - start.x) > 2 || fabs(loc.y - start.y) > 2)
-                       return kWasDragged;
-
-               if ((system_time() - start_time) > doubleClickSpeed) {
-                       ShowContextMenu(start);
-                       return kContextMenuShown;
-               }
-
-               snooze(15000);
-       }
-
-       // user let up on mouse button without dragging
-       Window()->Activate();
-       Window()->UpdateIfNeeded();
-       return kNotDragged;
-}
-
-
 void
 BPoseView::DeleteSymLinkPoseTarget(const node_ref *itemNode, BPose *pose,
        int32 index)
@@ -8391,14 +8441,16 @@
 void
 BPoseView::DrawAfterChildren(BRect updateRect)
 {
-       if (fTransparentSelection && fSelectionRect.IsValid()) {
+       if (fTransparentSelection && fSelectionRectInfo.rect.IsValid()) {
                SetDrawingMode(B_OP_ALPHA);
                SetHighColor(255, 255, 255, 128);
-               if (fSelectionRect.Width() == 0 || fSelectionRect.Height() == 0)
-                       StrokeLine(fSelectionRect.LeftTop(), 
fSelectionRect.RightBottom());
-               else {
-                       StrokeRect(fSelectionRect);
-                       BRect interior = fSelectionRect;
+               if (fSelectionRectInfo.rect.Width() == 0
+                       || fSelectionRectInfo.rect.Height() == 0) {
+                       StrokeLine(fSelectionRectInfo.rect.LeftTop(),
+                               fSelectionRectInfo.rect.RightBottom());
+               } else {
+                       StrokeRect(fSelectionRectInfo.rect);
+                       BRect interior = fSelectionRectInfo.rect;
                        interior.InsetBy(1, 1);
                        if (interior.IsValid()) {
                                SetHighColor(80, 80, 80, 90);
@@ -8947,82 +8999,6 @@
 }
 
 
-void
-BPoseView::MouseMoved(BPoint mouseLoc, uint32 moveCode, const BMessage 
*message)
-{
-       if (!fDropEnabled || !message)
-               return;
-
-       BContainerWindow* window = ContainerWindow();
-       if (!window)
-               return;
-
-       switch (moveCode) {
-               case B_INSIDE_VIEW:
-               case B_ENTERED_VIEW:
-               {
-                       UpdateDropTarget(mouseLoc, message, 
window->ContextMenu());
-                       if (fAutoScrollState == kAutoScrollOff) {
-                               // turn on auto scrolling if it's not yet on
-                               fAutoScrollState = kWaitForTransition;
-                               window->SetPulseRate(100000);
-                       }
-
-                       bigtime_t dropActionDelay;
-                       get_click_speed(&dropActionDelay);
-                       dropActionDelay *= 3;
-
-                       if (window->ContextMenu())
-                               break;
-
-                       bigtime_t clickTime = system_time();
-                       BPoint loc;
-                       uint32 buttons;
-                       GetMouse(&loc, &buttons);
-                       for (;;) {
-                               if (buttons == 0
-                                       || fabs(loc.x - mouseLoc.x) > 4 || 
fabs(loc.y - mouseLoc.y) > 4) {
-                                       // only loop if mouse buttons are down
-                                       // moved the mouse, cancel showing the 
context menu
-                                       break;
-                               }
-
-                               // handle drag and drop
-                               bigtime_t now = system_time();
-                               // use shift key to get around over-loading of 
Control key
-                               // for context menus and auto-dnd menu
-                               if (((modifiers() & B_SHIFT_KEY) && (now - 
clickTime) > 200000)
-                                       || now - clickTime > dropActionDelay) {
-                                       // let go of button or pressing for a 
while, show menu now
-                                       if (fDropTarget) {
-                                               window->DragStart(message);
-                                               FrameForPose(fDropTarget, true, 
&fStartFrame);
-                                               ShowContextMenu(mouseLoc);
-                                       } else
-                                               window->Activate();
-                                       break;
-                               }
-
-                               snooze(10000);
-                               GetMouse(&loc, &buttons);
-                       }
-                       break;
-               }
-
-               case B_EXITED_VIEW:
-                       // reset cursor in case we set it to the copy cursor in 
UpdateDropTarget
-                       SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
-                       fCursorCheck = false;
-                       // TODO: autoscroll here
-                       if (!window->ContextMenu()) {
-                               HiliteDropTarget(false);
-                               fDropTarget = NULL;
-                       }
-                       break;
-       }
-}
-
-
 bool
 BPoseView::UpdateDropTarget(BPoint mouseLoc, const BMessage *dragMessage,
        bool trackingContextMenu)

Modified: haiku/trunk/src/kits/tracker/PoseView.h
===================================================================
--- haiku/trunk/src/kits/tracker/PoseView.h     2011-06-03 21:11:38 UTC (rev 
41891)
+++ haiku/trunk/src/kits/tracker/PoseView.h     2011-06-03 21:12:14 UTC (rev 
41892)
@@ -161,10 +161,14 @@
                virtual void AttachedToWindow();
                virtual void WindowActivated(bool);
                virtual void MakeFocus(bool = true);
-               virtual void MouseMoved(BPoint, uint32, const BMessage *);
                virtual void Draw(BRect update_rect);
                virtual void DrawAfterChildren(BRect update_rect);
+               virtual void MouseMoved(BPoint, uint32, const BMessage *);
                virtual void MouseDown(BPoint where);
+               virtual void MouseUp(BPoint where);
+               virtual void MouseDragged(const BMessage *);
+               virtual void MouseLongDown(const BMessage *);
+               virtual void MouseIdle(const BMessage *);
                virtual void KeyDown(const char *, int32);
                virtual void Pulse();
                virtual void MoveBy(float, float);
@@ -355,7 +359,6 @@
                static bool CanHandleDragSelection(const Model *target,
                        const BMessage *dragMessage, bool ignoreTypes);
                virtual void DragSelectedPoses(const BPose *clickedPose, 
BPoint);
-               virtual void DragSelectionRect(BPoint, bool extendSelection);
 
                void MoveSelectionInto(Model *destFolder, BContainerWindow 
*srcWindow,
                        bool forceCopy, bool forceMove = false, bool createLink 
= false, bool relativeLink = false);
@@ -574,13 +577,16 @@
                // click handling
                bool WasDoubleClick(const BPose *, BPoint);
                bool WasClickInPath(const BPose *, int32 index, BPoint) const;
-               int32 WaitForMouseUpOrDrag(BPoint start);
 
                // selection
                void SelectPosesListMode(BRect, BList **);
                void SelectPosesIconMode(BRect, BList **);
                void AddRemoveSelectionRange(BPoint where, bool 
extendSelection, BPose *);
 
+               void _BeginSelectionRect(const BPoint& point, bool 
extendSelection);
+               void _UpdateSelectionRect(const BPoint& point);
+               void _EndSelectionRect();
+
                // view drawing
                void SynchronousUpdate(BRect, bool clip = false);
 
@@ -685,6 +691,18 @@
                const BPose *fRealPivotPose;
                BMessageRunner *fKeyRunner;
 
+               struct SelectionRectInfo {
+                                       SelectionRectInfo()
+                                               :       isDragging(false), 
selection(NULL) {};
+                       bool    isDragging;
+                       BRect   rect;
+                       BRect   lastRect;
+                       BPoint  startPoint;
+                       BPoint  lastPoint;
+                       BList*  selection;
+               };
+               SelectionRectInfo fSelectionRectInfo;
+
                bool fSelectionVisible : 1;
                bool fMultipleSelection : 1;
                bool fDragEnabled : 1;
@@ -709,7 +727,6 @@
                int32 fLastFilterStringLength;
 
                BRect fStartFrame;
-               BRect fSelectionRect;
 
                static float sFontHeight;
                static font_height sFontInfo;


Other related posts:

  • » [haiku-commits] r41892 - in haiku/trunk: headers/private/shared src/kits/shared src/kits/tracker - alex