HaikuDepot: notify work status from main window
[haiku.git] / src / kits / shared / LongAndDragTrackingFilter.cpp
blob754a3cf50055bbb90301d1dd31e42e390cc53159
1 /*
2 * Copyright 2011, Alexandre Deckner, alex@zappotek.com
3 * Distributed under the terms of the MIT License.
4 */
6 /*!
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>
29 #include <Message.h>
30 #include <Messenger.h>
31 #include <MessageRunner.h>
32 #include <View.h>
34 #include <new>
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),
44 fMessageRunner(NULL),
45 fClickButtons(0),
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;
62 void
63 LongAndDragTrackingFilter::_StopTracking()
65 delete fMessageRunner;
66 fMessageRunner = NULL;
70 filter_result
71 LongAndDragTrackingFilter::Filter(BMessage* message, BHandler** target)
73 if (*target == NULL)
74 return B_DISPATCH_MESSAGE;
76 switch (message->what) {
77 case B_MOUSE_DOWN:
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;
98 case B_MOUSE_UP:
99 _StopTracking();
100 message->AddInt32("last_buttons", (int32)fClickButtons);
101 return B_DISPATCH_MESSAGE;
103 case B_MOUSE_MOVED:
105 if (fMessageRunner != NULL) {
106 BPoint where;
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);
122 _StopTracking();
125 return B_DISPATCH_MESSAGE;
128 default:
129 if (message->what == fLongMessageWhat) {
130 _StopTracking();
131 return B_DISPATCH_MESSAGE;
133 break;
136 return B_DISPATCH_MESSAGE;