* Rewrote BDragger's mouse tracking to be asynchronous using a message filter. Placed the filter in
kits/shared since i plan to use it in other places like Tracker. Animated replicants like ActivityMonitor wont stall anymore when initiating the drag. (On the desktop, Tracker's mouse tracking still busy loops sometimes, that's next on my list). I had asynchronous long click detection (one button mouse support) in it but decided to get rid of it, it adds unneeded complexity in the code and is even getting in your way sometimes (ex: now you can take your time to drag the dragger, you wont be interrupted). If we want to reimplement that someday it should be done system wide anyway (only Tracker and replicants have that 'feature' AFAIK). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29972 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _DRAGGER_H
|
||||
@@ -115,7 +115,7 @@ class BDragger : public BView {
|
||||
bool fIsZombie;
|
||||
char fErrCount;
|
||||
bool fPopUpIsCustom;
|
||||
BBitmap * fBitmap;
|
||||
BBitmap* fBitmap;
|
||||
BPopUpMenu* fPopUp;
|
||||
uint32 _reserved[3];
|
||||
};
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2009, Alexandre Deckner, [email protected]
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DRAG_TRACKING_FILTER_H
|
||||
#define DRAG_TRACKING_FILTER_H
|
||||
|
||||
#include <MessageFilter.h>
|
||||
#include <Point.h>
|
||||
|
||||
class BView;
|
||||
class BHandler;
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
class DragTrackingFilter : public BMessageFilter {
|
||||
public:
|
||||
DragTrackingFilter(BView* targetView, uint32 messageWhat);
|
||||
|
||||
filter_result Filter(BMessage* message, BHandler** _target);
|
||||
|
||||
private:
|
||||
BView* fTargetView;
|
||||
uint32 fMessageWhat;
|
||||
bool fIsTracking;
|
||||
BPoint fClickPoint;
|
||||
uint32 fClickButtons;
|
||||
};
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
using BPrivate::DragTrackingFilter;
|
||||
|
||||
#endif // DRAG_TRACKING_FILTER_H
|
||||
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* Copyright 2001-2008, Haiku.
|
||||
* Copyright 2001-2009, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Marc Flerackers ([email protected])
|
||||
* Rene Gollent ([email protected])
|
||||
* Alexandre Deckner ([email protected])
|
||||
*/
|
||||
|
||||
//! BDragger represents a replicant "handle".
|
||||
@@ -25,6 +26,7 @@
|
||||
#include <Window.h>
|
||||
|
||||
#include <AppServerLink.h>
|
||||
#include <DragTrackingFilter.h>
|
||||
#include <binary_compatibility/Interface.h>
|
||||
#include <ServerProtocol.h>
|
||||
#include <ViewPrivate.h>
|
||||
@@ -37,6 +39,7 @@ bool BDragger::sVisibleInitialized;
|
||||
BLocker BDragger::sLock("BDragger static");
|
||||
BList BDragger::sList;
|
||||
|
||||
const uint32 kMsgDragStarted = 'Drgs';
|
||||
|
||||
const unsigned char
|
||||
kHandBitmap[] = {
|
||||
@@ -153,6 +156,8 @@ BDragger::AttachedToWindow()
|
||||
|
||||
_DetermineRelationship();
|
||||
_AddToList();
|
||||
|
||||
AddFilter(new DragTrackingFilter(this, kMsgDragStarted));
|
||||
}
|
||||
|
||||
|
||||
@@ -211,73 +216,8 @@ BDragger::MouseDown(BPoint where)
|
||||
uint32 buttons;
|
||||
Window()->CurrentMessage()->FindInt32("buttons", (int32 *)&buttons);
|
||||
|
||||
if (buttons & B_SECONDARY_MOUSE_BUTTON) {
|
||||
if (!fShelf)
|
||||
return;
|
||||
|
||||
if (fShelf != NULL && (buttons & B_SECONDARY_MOUSE_BUTTON))
|
||||
_ShowPopUp(fTarget, where);
|
||||
} else {
|
||||
bigtime_t time = system_time();
|
||||
bigtime_t clickSpeed = 0;
|
||||
|
||||
get_click_speed(&clickSpeed);
|
||||
|
||||
bool drag = false;
|
||||
|
||||
while (true) {
|
||||
BPoint mousePoint;
|
||||
GetMouse(&mousePoint, &buttons, false);
|
||||
|
||||
if (!buttons || system_time() > time + clickSpeed)
|
||||
break;
|
||||
|
||||
float squaredDistance =
|
||||
(mousePoint.x - where.x) * (mousePoint.x - where.x)
|
||||
+ (mousePoint.y - where.y) * (mousePoint.y - where.y);
|
||||
|
||||
if (squaredDistance >= 16) {
|
||||
drag = true;
|
||||
break;
|
||||
}
|
||||
|
||||
snooze(40000);
|
||||
}
|
||||
|
||||
if (drag) {
|
||||
BMessage archive(B_ARCHIVED_OBJECT);
|
||||
|
||||
if (fRelation == TARGET_IS_PARENT)
|
||||
fTarget->Archive(&archive);
|
||||
else if (fRelation == TARGET_IS_CHILD)
|
||||
Archive(&archive);
|
||||
else {
|
||||
if (fTarget->Archive(&archive)) {
|
||||
BMessage archivedSelf(B_ARCHIVED_OBJECT);
|
||||
|
||||
if (Archive(&archivedSelf))
|
||||
archive.AddMessage("__widget", &archivedSelf);
|
||||
}
|
||||
}
|
||||
|
||||
archive.AddInt32("be:actions", B_TRASH_TARGET);
|
||||
|
||||
BPoint offset;
|
||||
drawing_mode mode;
|
||||
BBitmap *bitmap = DragBitmap(&offset, &mode);
|
||||
if (bitmap != NULL)
|
||||
DragMessage(&archive, bitmap, mode, offset, this);
|
||||
else {
|
||||
DragMessage(&archive,
|
||||
ConvertFromScreen(fTarget->ConvertToScreen(fTarget->Bounds())),
|
||||
this);
|
||||
}
|
||||
} else {
|
||||
if (!fShelf)
|
||||
return;
|
||||
|
||||
_ShowPopUp(fTarget, where);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -328,6 +268,37 @@ BDragger::MessageReceived(BMessage *msg)
|
||||
}
|
||||
break;
|
||||
|
||||
case kMsgDragStarted:
|
||||
if (fTarget != NULL) {
|
||||
BMessage archive(B_ARCHIVED_OBJECT);
|
||||
|
||||
if (fRelation == TARGET_IS_PARENT)
|
||||
fTarget->Archive(&archive);
|
||||
else if (fRelation == TARGET_IS_CHILD)
|
||||
Archive(&archive);
|
||||
else {
|
||||
if (fTarget->Archive(&archive)) {
|
||||
BMessage archivedSelf(B_ARCHIVED_OBJECT);
|
||||
|
||||
if (Archive(&archivedSelf))
|
||||
archive.AddMessage("__widget", &archivedSelf);
|
||||
}
|
||||
}
|
||||
|
||||
archive.AddInt32("be:actions", B_TRASH_TARGET);
|
||||
BPoint offset;
|
||||
drawing_mode mode;
|
||||
BBitmap *bitmap = DragBitmap(&offset, &mode);
|
||||
if (bitmap != NULL)
|
||||
DragMessage(&archive, bitmap, mode, offset, this);
|
||||
else {
|
||||
DragMessage(&archive,
|
||||
ConvertFromScreen(fTarget->ConvertToScreen(fTarget->Bounds())),
|
||||
this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BView::MessageReceived(msg);
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2009, Alexandre Deckner, [email protected]
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class DragTrackingFilter
|
||||
\brief A simple mouse drag detection filter
|
||||
*
|
||||
* A simple mouse filter that detects the start of a mouse drag over a
|
||||
* threshold distance and sends a message with the 'what' field of your
|
||||
* choice. Especially usefull for drag and drop.
|
||||
* Allows you to free your code of encumbering mouse tracking details.
|
||||
*
|
||||
* It can detect fast drags spanning outside of a small view by temporarily
|
||||
* setting the B_POINTER_EVENTS flag on the view.
|
||||
*/
|
||||
|
||||
#include <DragTrackingFilter.h>
|
||||
|
||||
#include <Message.h>
|
||||
#include <Messenger.h>
|
||||
#include <View.h>
|
||||
|
||||
static const int kSquaredDragThreshold = 9;
|
||||
|
||||
DragTrackingFilter::DragTrackingFilter(BView* targetView, uint32 messageWhat)
|
||||
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
|
||||
fTargetView(targetView),
|
||||
fMessageWhat(messageWhat),
|
||||
fIsTracking(false),
|
||||
fClickButtons(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
filter_result
|
||||
DragTrackingFilter::Filter(BMessage* message, BHandler** /*_target*/)
|
||||
{
|
||||
if (fTargetView == NULL)
|
||||
return B_DISPATCH_MESSAGE;
|
||||
|
||||
switch (message->what) {
|
||||
case B_MOUSE_DOWN:
|
||||
message->FindPoint("where", &fClickPoint);
|
||||
message->FindInt32("buttons", (int32*)&fClickButtons);
|
||||
fIsTracking = true;
|
||||
|
||||
fTargetView->SetMouseEventMask(B_POINTER_EVENTS);
|
||||
|
||||
return B_DISPATCH_MESSAGE;
|
||||
|
||||
case B_MOUSE_UP:
|
||||
fIsTracking = false;
|
||||
return B_DISPATCH_MESSAGE;
|
||||
|
||||
case B_MOUSE_MOVED:
|
||||
{
|
||||
BPoint where;
|
||||
message->FindPoint("be:view_where", &where);
|
||||
|
||||
// TODO: be more flexible about buttons and pass their state
|
||||
// in the message
|
||||
if (fIsTracking && (fClickButtons & B_PRIMARY_MOUSE_BUTTON)) {
|
||||
|
||||
BPoint delta(fClickPoint - where);
|
||||
float squaredDelta = (delta.x * delta.x) + (delta.y * delta.y);
|
||||
|
||||
if (squaredDelta >= kSquaredDragThreshold) {
|
||||
BMessage dragClickMessage(fMessageWhat);
|
||||
dragClickMessage.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
|
||||
BMessenger messenger(fTargetView);
|
||||
messenger.SendMessage(&dragClickMessage);
|
||||
|
||||
fIsTracking = false;
|
||||
}
|
||||
}
|
||||
return B_DISPATCH_MESSAGE;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return B_DISPATCH_MESSAGE;
|
||||
}
|
||||
@@ -17,6 +17,7 @@ StaticLibrary libshared.a :
|
||||
ColorQuantizer.cpp
|
||||
CommandPipe.cpp
|
||||
DateTime.cpp
|
||||
DragTrackingFilter.cpp
|
||||
HashString.cpp
|
||||
RWLockManager.cpp
|
||||
;
|
||||
|
||||
Reference in New Issue
Block a user