2 * Copyright 2011, Alexandre Deckner, alex@zappotek.com
3 * Distributed under the terms of the MIT License.
7 \class LongAndDragTrackingFilter
8 \brief A simple long mouse down and drag detection filter
10 * A simple mouse filter that detects long clicks and pointer drags.
11 * A long click message is sent when the mouse button is kept down
12 * for a duration longer than a given threshold while the pointer stays
13 * within the limits of a given threshold radius.
14 * A drag message is triggered if the mouse goes further than the
15 * threshold radius before the duration threshold elapsed.
17 * The messages contain the pointer position and the buttons state at
18 * the moment of the click. The drag message is ready to use with the
19 * be/haiku drag and drop API cf. comment in code.
21 * Current limitation: A long mouse down or a drag can be detected for
22 * any mouse button, but any released button cancels the tracking.
27 #include <LongAndDragTrackingFilter.h>
30 #include <Messenger.h>
31 #include <MessageRunner.h>
37 LongAndDragTrackingFilter::LongAndDragTrackingFilter(uint32 longMessageWhat
,
38 uint32 dragMessageWhat
, float radiusThreshold
,
39 bigtime_t durationThreshold
)
41 BMessageFilter(B_ANY_DELIVERY
, B_ANY_SOURCE
),
42 fLongMessageWhat(longMessageWhat
),
43 fDragMessageWhat(dragMessageWhat
),
46 fSquaredRadiusThreshold(radiusThreshold
* radiusThreshold
),
47 fDurationThreshold(durationThreshold
)
49 if (durationThreshold
== 0) {
50 get_click_speed(&fDurationThreshold
);
51 // use system's doubleClickSpeed as default threshold
56 LongAndDragTrackingFilter::~LongAndDragTrackingFilter()
58 delete fMessageRunner
;
63 LongAndDragTrackingFilter::_StopTracking()
65 delete fMessageRunner
;
66 fMessageRunner
= NULL
;
71 LongAndDragTrackingFilter::Filter(BMessage
* message
, BHandler
** target
)
74 return B_DISPATCH_MESSAGE
;
76 switch (message
->what
) {
79 message
->FindInt32("buttons", (int32
*)&fClickButtons
);
81 if (fClickButtons
!= 0) {
83 BView
* targetView
= dynamic_cast<BView
*>(*target
);
84 if (targetView
!= NULL
)
85 targetView
->SetMouseEventMask(B_POINTER_EVENTS
);
87 message
->FindPoint("where", &fClickPoint
);
88 BMessage
message(fLongMessageWhat
);
89 message
.AddPoint("where", fClickPoint
);
90 message
.AddInt32("buttons", fClickButtons
);
92 delete fMessageRunner
;
93 fMessageRunner
= new (std::nothrow
) BMessageRunner(
94 BMessenger(*target
), &message
, fDurationThreshold
, 1);
96 return B_DISPATCH_MESSAGE
;
100 message
->AddInt32("last_buttons", (int32
)fClickButtons
);
101 return B_DISPATCH_MESSAGE
;
105 if (fMessageRunner
!= NULL
) {
107 message
->FindPoint("be:view_where", &where
);
109 BPoint
delta(fClickPoint
- where
);
110 float squaredDelta
= (delta
.x
* delta
.x
) + (delta
.y
* delta
.y
);
112 if (squaredDelta
>= fSquaredRadiusThreshold
) {
113 BMessage
dragMessage(fDragMessageWhat
);
114 dragMessage
.AddPoint("be:view_where", fClickPoint
);
115 // name it "be:view_where" since BView::DragMessage
116 // positions the dragging frame/bitmap by retrieving
117 // the current message and reading that field
118 dragMessage
.AddInt32("buttons", (int32
)fClickButtons
);
119 BMessenger
messenger(*target
);
120 messenger
.SendMessage(&dragMessage
);
125 return B_DISPATCH_MESSAGE
;
129 if (message
->what
== fLongMessageWhat
) {
131 return B_DISPATCH_MESSAGE
;
136 return B_DISPATCH_MESSAGE
;