342229 NS_DRAGDROP_OVER/ondragover should fire repeatedly when performing a drag, even when the mouse is not moving. r=josh sr=bryner

This commit is contained in:
mark%moxienet.com 2006-06-26 20:45:55 +00:00
Родитель db68ff7b6c
Коммит f3f13838bb
2 изменённых файлов: 128 добавлений и 38 удалений

Просмотреть файл

@ -54,6 +54,8 @@ NS_IMPL_QUERY_INTERFACE1(nsDragHelperService, nsIDragHelperService)
// nsDragHelperService constructor
//
nsDragHelperService::nsDragHelperService()
: mDragOverTimer(nsnull)
, mDragOverDragRef(nsnull)
{
}
@ -63,6 +65,9 @@ nsDragHelperService::nsDragHelperService()
//
nsDragHelperService::~nsDragHelperService()
{
if (mDragOverTimer)
::RemoveEventLoopTimer(mDragOverTimer);
NS_ASSERTION(!mDragService.get(),
"A drag was not correctly ended by shutdown");
}
@ -92,13 +97,10 @@ nsDragHelperService::Enter(DragReference inDragRef, nsIEventSink *inSink)
if (macSession)
macSession->SetDragReference(inDragRef);
// let gecko know that the mouse has entered the window so it
// can start tracking and sending enter/exit events to frames.
Point mouseLocGlobal;
::GetDragMouse(inDragRef, &mouseLocGlobal, nsnull);
PRBool handled = PR_FALSE;
inSink->DragEvent(NS_DRAGDROP_ENTER, mouseLocGlobal.h, mouseLocGlobal.v, 0L,
&handled);
DoDragAction(NS_DRAGDROP_ENTER, inDragRef, inSink);
// Start sending regular NS_DRAGDROP_OVER events.
SetDragOverTimer(inSink, inDragRef);
return NS_OK;
}
@ -107,7 +109,7 @@ nsDragHelperService::Enter(DragReference inDragRef, nsIEventSink *inSink)
//
// Tracking
//
// Called while the mouse is inside the rectangle bounding the browser
// Called while the mouse is moved inside the rectangle bounding the browser
// during a drag. The important thing done here is to clear the |canDrop|
// property of the drag session every time through. The event handlers
// will reset it if appropriate.
@ -123,14 +125,6 @@ nsDragHelperService::Tracking(DragReference inDragRef, nsIEventSink *inSink,
return NS_ERROR_FAILURE;
}
Point mouseLocGlobal;
::GetDragMouse(inDragRef, &mouseLocGlobal, nsnull);
short modifiers;
::GetDragModifiers(inDragRef, &modifiers, nsnull, nsnull);
// set the drag action on the service so the frames know what is going on
SetDragActionBasedOnModifiers(modifiers);
// clear out the |canDrop| property of the drag session. If it's meant to
// be, it will be set again.
nsCOMPtr<nsIDragSession> session;
@ -139,10 +133,11 @@ nsDragHelperService::Tracking(DragReference inDragRef, nsIEventSink *inSink,
if (session)
session->SetCanDrop(PR_FALSE);
// pass into gecko for handling...
PRBool handled = PR_FALSE;
inSink->DragEvent(NS_DRAGDROP_OVER, mouseLocGlobal.h, mouseLocGlobal.v,
modifiers, &handled);
// mDragOverTimer is running, but an NS_DRAGDROP_OVER event is about to be
// sent. Make sure that the timer doesn't send another event too quickly.
SetDragOverTimer(inSink, inDragRef);
DoDragAction(NS_DRAGDROP_OVER, inDragRef, inSink);
// check if gecko has since allowed the drop and return it
if (session)
@ -161,6 +156,9 @@ nsDragHelperService::Tracking(DragReference inDragRef, nsIEventSink *inSink,
NS_IMETHODIMP
nsDragHelperService::Leave(DragReference inDragRef, nsIEventSink *inSink)
{
// Stop sending NS_DRAGDROP_OVER events.
SetDragOverTimer(nsnull, nsnull);
NS_ASSERTION(mDragService,
"Couldn't get a drag service, we're in biiig trouble");
if (!mDragService || !inSink)
@ -174,13 +172,7 @@ nsDragHelperService::Leave(DragReference inDragRef, nsIEventSink *inSink)
if (macSession)
macSession->SetDragReference(0);
// let gecko know that the mouse has left the window so it
// can stop tracking and sending enter/exit events to frames.
Point mouseLocGlobal;
::GetDragMouse(inDragRef, &mouseLocGlobal, nsnull);
PRBool handled = PR_FALSE;
inSink->DragEvent(NS_DRAGDROP_EXIT, mouseLocGlobal.h, mouseLocGlobal.v, 0L,
&handled);
DoDragAction(NS_DRAGDROP_EXIT, inDragRef, inSink);
#ifndef MOZ_WIDGET_COCOA
::HideDragHilite(inDragRef);
@ -219,6 +211,9 @@ NS_IMETHODIMP
nsDragHelperService::Drop(DragReference inDragRef, nsIEventSink *inSink,
PRBool* outAccepted)
{
// Stop sending NS_DRAGDROP_OVER events.
SetDragOverTimer(nsnull, nsnull);
NS_ASSERTION(mDragService,
"Couldn't get a drag service, we're in biiig trouble");
if (!mDragService || !inSink) {
@ -238,16 +233,8 @@ nsDragHelperService::Drop(DragReference inDragRef, nsIEventSink *inSink,
// to gecko, otherwise set phasers for failure.
PRBool canDrop = PR_FALSE;
if (NS_SUCCEEDED(dragSession->GetCanDrop(&canDrop)))
if (canDrop) {
// pass the drop event along to Gecko
Point mouseLocGlobal;
::GetDragMouse(inDragRef, &mouseLocGlobal, nsnull);
short modifiers;
::GetDragModifiers(inDragRef, &modifiers, nsnull, nsnull);
PRBool handled = PR_FALSE;
inSink->DragEvent(NS_DRAGDROP_DROP, mouseLocGlobal.h, mouseLocGlobal.v,
modifiers, &handled);
}
if (canDrop)
DoDragAction(NS_DRAGDROP_DROP, inDragRef, inSink);
else
result = dragNotAcceptedErr;
} // if a valid drag session
@ -263,6 +250,35 @@ nsDragHelperService::Drop(DragReference inDragRef, nsIEventSink *inSink,
}
// DoDragAction
//
// Common routine for NS_DRAGDROP_(ENTER|EXIT|OVER|DROP) events. Obtains
// information about the drag in progress and dispatches the event.
//
// protected
PRBool
nsDragHelperService::DoDragAction(PRUint32 aMessage,
DragReference aDragRef,
nsIEventSink* aSink)
{
// Get information about the drag.
Point mouseLocGlobal;
::GetDragMouse(aDragRef, &mouseLocGlobal, nsnull);
short modifiers;
::GetDragModifiers(aDragRef, &modifiers, nsnull, nsnull);
// Set the drag action on the service so the frames know what is going on.
SetDragActionBasedOnModifiers(modifiers);
// Pass into Gecko for handling.
PRBool handled = PR_FALSE;
aSink->DragEvent(aMessage, mouseLocGlobal.h, mouseLocGlobal.v,
modifiers, &handled);
return handled;
}
//
// SetDragActionsBasedOnModifiers
//
@ -290,3 +306,64 @@ nsDragHelperService::SetDragActionBasedOnModifiers(short inModifiers)
} // SetDragActionBasedOnModifiers
// SetDragOverTimer
//
// Sets a timer to send NS_DRAGDROP_OVER events into Gecko at regular
// intervals. If a timer is already running, the interval is reset.
// If either argument is null, any running timer is stopped.
//
// protected
void
nsDragHelperService::SetDragOverTimer(nsIEventSink* aSink,
DragRef aDragRef)
{
// win32 seems to use 16Hz internally, gtk2 has a 10Hz timer
const EventTimerInterval kDragOverInterval = 1.0/10.0;
if (!aSink || !aDragRef) {
// Cancel the timer.
if (mDragOverTimer) {
::RemoveEventLoopTimer(mDragOverTimer);
mDragOverTimer = nsnull;
mDragOverSink = nsnull;
}
return;
}
if (mDragOverTimer) {
// A timer is already running, just bump its next-fire time.
::SetEventLoopTimerNextFireTime(mDragOverTimer, kDragOverInterval);
return;
}
mDragOverSink = aSink;
mDragOverDragRef = aDragRef;
static EventLoopTimerUPP sDragOverTimerUPP;
if (!sDragOverTimerUPP)
sDragOverTimerUPP = ::NewEventLoopTimerUPP(DragOverTimerHandler);
::InstallEventLoopTimer(::GetCurrentEventLoop(),
kDragOverInterval,
kDragOverInterval,
sDragOverTimerUPP,
this,
&mDragOverTimer);
}
// DragOverTimerHandler
//
// Called at regular intervals to send NS_DRAGDROP_OVER events.
//
// protected static
void
nsDragHelperService::DragOverTimerHandler(EventLoopTimerRef aTimer,
void* aUserData)
{
nsDragHelperService* self = NS_STATIC_CAST(nsDragHelperService*, aUserData);
self->DoDragAction(NS_DRAGDROP_OVER,
self->mDragOverDragRef, self->mDragOverSink);
}

Просмотреть файл

@ -41,7 +41,7 @@
#include "nsCOMPtr.h"
#include "nsIDragService.h"
#include <Drag.h>
#include <Carbon/Carbon.h>
#include "nsIDragHelperService.h"
@ -69,9 +69,18 @@ public:
protected:
// Send a drag event into Gecko
PRBool DoDragAction(PRUint32 aMessage,
DragReference aDragRef,
nsIEventSink* aSink);
// handles modifier keys (cmd, option, etc) and sets the appropriate
// action (move, copy, etc) based on the given modifiers.
void SetDragActionBasedOnModifiers ( short inModifiers ) ;
// Arranges to send NS_DRAGDROP_OVER events at regular intervals
void SetDragOverTimer(nsIEventSink* aSink, DragRef aDragRef);
static void DragOverTimerHandler(EventLoopTimerRef aTimer, void* aUserData);
// holds our drag service across multiple calls to this callback. The reference to
// the service is obtained when the mouse enters the window and is released when
@ -80,6 +89,10 @@ protected:
// handling the |kDragTrackingInWindow| message.
nsCOMPtr<nsIDragService> mDragService;
// Used to implement the NS_DRAGDROP_OVER timer
EventLoopTimerRef mDragOverTimer;
nsCOMPtr<nsIEventSink> mDragOverSink;
DragRef mDragOverDragRef;
}; // nsDragHelperService