mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
b=497498 schedule event dispatch in response to GTK drag target signals to avoid running the event loop at unexpected times r=roc
--HG-- extra : rebase_source : 881ad7c0efa85174347059a9f53b3a5bd4c76696
This commit is contained in:
parent
c2121f5398
commit
a5dc82ba4e
@ -127,6 +127,7 @@ invisibleSourceDragDataGet(GtkWidget *aWidget,
|
|||||||
gpointer aData);
|
gpointer aData);
|
||||||
|
|
||||||
nsDragService::nsDragService()
|
nsDragService::nsDragService()
|
||||||
|
: mTaskSource(0)
|
||||||
{
|
{
|
||||||
// We have to destroy the hidden widget before the event loop stops
|
// We have to destroy the hidden widget before the event loop stops
|
||||||
// running.
|
// running.
|
||||||
@ -162,9 +163,6 @@ nsDragService::nsDragService()
|
|||||||
sDragLm = PR_NewLogModule("nsDragService");
|
sDragLm = PR_NewLogModule("nsDragService");
|
||||||
PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::nsDragService"));
|
PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::nsDragService"));
|
||||||
mGrabWidget = 0;
|
mGrabWidget = 0;
|
||||||
mTargetWidget = 0;
|
|
||||||
mTargetDragContext = 0;
|
|
||||||
mTargetTime = 0;
|
|
||||||
mCanDrop = false;
|
mCanDrop = false;
|
||||||
mTargetDragDataReceived = false;
|
mTargetDragDataReceived = false;
|
||||||
mTargetDragData = 0;
|
mTargetDragData = 0;
|
||||||
@ -174,6 +172,9 @@ nsDragService::nsDragService()
|
|||||||
nsDragService::~nsDragService()
|
nsDragService::~nsDragService()
|
||||||
{
|
{
|
||||||
PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::~nsDragService"));
|
PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::~nsDragService"));
|
||||||
|
if (mTaskSource)
|
||||||
|
g_source_remove(mTaskSource);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED2(nsDragService, nsBaseDragService,
|
NS_IMPL_ISUPPORTS_INHERITED2(nsDragService, nsBaseDragService,
|
||||||
@ -1131,7 +1132,8 @@ nsDragService::GetTargetDragData(GdkAtom aFlavor)
|
|||||||
{
|
{
|
||||||
PR_LOG(sDragLm, PR_LOG_DEBUG, ("getting data flavor %d\n", aFlavor));
|
PR_LOG(sDragLm, PR_LOG_DEBUG, ("getting data flavor %d\n", aFlavor));
|
||||||
PR_LOG(sDragLm, PR_LOG_DEBUG, ("mLastWidget is %p and mLastContext is %p\n",
|
PR_LOG(sDragLm, PR_LOG_DEBUG, ("mLastWidget is %p and mLastContext is %p\n",
|
||||||
mTargetWidget, mTargetDragContext));
|
mTargetWidget.get(),
|
||||||
|
mTargetDragContext.get()));
|
||||||
// reset our target data areas
|
// reset our target data areas
|
||||||
TargetResetData();
|
TargetResetData();
|
||||||
gtk_drag_get_data(mTargetWidget, mTargetDragContext, aFlavor, mTargetTime);
|
gtk_drag_get_data(mTargetWidget, mTargetDragContext, aFlavor, mTargetTime);
|
||||||
@ -1702,3 +1704,231 @@ invisibleSourceDragEnd(GtkWidget *aWidget,
|
|||||||
dragService->SourceEndDragSession(aContext, MOZ_GTK_DRAG_RESULT_SUCCESS);
|
dragService->SourceEndDragSession(aContext, MOZ_GTK_DRAG_RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The following methods handle responding to GTK drag destination signals and
|
||||||
|
// tracking state between these signals.
|
||||||
|
//
|
||||||
|
// In general, GTK does not expect us to run the event loop while handling its
|
||||||
|
// drag destination signals, however our drag event handlers may run the
|
||||||
|
// event loop, most often to fetch information about the drag data.
|
||||||
|
//
|
||||||
|
// GTK, for example, uses the return value from drag-motion signals to
|
||||||
|
// determine whether drag-leave signals should be sent. If an event loop is
|
||||||
|
// run during drag-motion the XdndLeave message can get processed but when GTK
|
||||||
|
// receives the message it does not yet know that it needs to send the
|
||||||
|
// drag-leave signal to our widget.
|
||||||
|
//
|
||||||
|
// After a drag-drop signal, we need to reply with gtk_drag_finish().
|
||||||
|
// However, gtk_drag_finish should happen after the drag-drop signal handler
|
||||||
|
// returns so that when the Motif drag protocol is used, the
|
||||||
|
// XmTRANSFER_SUCCESS during gtk_drag_finish is sent after the XmDROP_START
|
||||||
|
// reply sent on return from the drag-drop signal handler.
|
||||||
|
//
|
||||||
|
// Therefore we reply to the signals immediately and schedule a task to
|
||||||
|
// dispatch the Gecko events, which may run the event loop.
|
||||||
|
//
|
||||||
|
// Action in response to drag-leave signals is also delayed until the event
|
||||||
|
// loop runs again so that we find out whether a drag-drop signal follows.
|
||||||
|
//
|
||||||
|
// A single task is scheduled to manage responses to all three GTK signals.
|
||||||
|
// If further signals are received while the task is scheduled, the scheduled
|
||||||
|
// response is updated, sometimes effectively compressing successive signals.
|
||||||
|
//
|
||||||
|
// No Gecko drag events are dispatched (during nested event loops) while other
|
||||||
|
// Gecko drag events are in flight. This helps event handlers that may not
|
||||||
|
// expect nested events, while accessing an event's dataTransfer for example.
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nsDragService::ScheduleMotionEvent(nsWindow *aWindow,
|
||||||
|
GdkDragContext *aDragContext,
|
||||||
|
nsIntPoint aWindowPoint, guint aTime)
|
||||||
|
{
|
||||||
|
if (mScheduledTask == eDragTaskMotion) {
|
||||||
|
// The drag source has sent another motion message before we've
|
||||||
|
// replied to the previous. That shouldn't happen with Xdnd. The
|
||||||
|
// spec for Motif drags is less clear, but we'll just update the
|
||||||
|
// scheduled task with the new position reply only to the most
|
||||||
|
// recent message.
|
||||||
|
NS_WARNING("Drag Motion message received before previous reply was sent");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returning TRUE means we'll reply with a status message, unless we first
|
||||||
|
// get a leave.
|
||||||
|
return Schedule(eDragTaskMotion, aWindow, aDragContext,
|
||||||
|
aWindowPoint, aTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsDragService::ScheduleLeaveEvent()
|
||||||
|
{
|
||||||
|
// We don't know at this stage whether a drop signal will immediately
|
||||||
|
// follow. If the drop signal gets sent it will happen before we return
|
||||||
|
// to the main loop and the scheduled leave task will be replaced.
|
||||||
|
if (!Schedule(eDragTaskLeave, nsnull, NULL, nsIntPoint(), 0)) {
|
||||||
|
NS_WARNING("Drag leave after drop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nsDragService::ScheduleDropEvent(nsWindow *aWindow,
|
||||||
|
GdkDragContext *aDragContext,
|
||||||
|
nsIntPoint aWindowPoint, guint aTime)
|
||||||
|
{
|
||||||
|
if (!Schedule(eDragTaskDrop, aWindow,
|
||||||
|
aDragContext, aWindowPoint, aTime)) {
|
||||||
|
NS_WARNING("Additional drag drop ignored");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetDragEndPoint(aWindowPoint + aWindow->WidgetToScreenOffset());
|
||||||
|
|
||||||
|
// We'll reply with gtk_drag_finish().
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nsDragService::Schedule(DragTask aTask, nsWindow *aWindow,
|
||||||
|
GdkDragContext *aDragContext,
|
||||||
|
nsIntPoint aWindowPoint, guint aTime)
|
||||||
|
{
|
||||||
|
// If we haven't yet run a scheduled drop task, just say that
|
||||||
|
// we are not ready to receive another drop.
|
||||||
|
if (mScheduledTask == eDragTaskDrop)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// If there is an existing leave or motion task scheduled, then that
|
||||||
|
// will be replaced. When the new task is run, it will dispatch
|
||||||
|
// any necessary leave or motion events.
|
||||||
|
|
||||||
|
mScheduledTask = aTask;
|
||||||
|
mPendingWindow = aWindow;
|
||||||
|
mPendingDragContext = aDragContext;
|
||||||
|
mPendingWindowPoint = aWindowPoint;
|
||||||
|
mPendingTime = aTime;
|
||||||
|
|
||||||
|
if (!mTaskSource) {
|
||||||
|
// High priority is used here because the native events involved have
|
||||||
|
// already waited at default priority. Perhaps a lower than default
|
||||||
|
// priority could be used for motion tasks because there is a chance
|
||||||
|
// that a leave or drop is waiting, but managing different priorities
|
||||||
|
// may not be worth the effort. Motion tasks shouldn't queue up as
|
||||||
|
// they should be throttled based on replies.
|
||||||
|
mTaskSource =
|
||||||
|
g_idle_add_full(G_PRIORITY_HIGH, TaskDispatchCallback, this, NULL);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nsDragService::TaskDispatchCallback(gpointer data)
|
||||||
|
{
|
||||||
|
nsRefPtr<nsDragService> dragService = static_cast<nsDragService*>(data);
|
||||||
|
return dragService->RunScheduledTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nsDragService::RunScheduledTask()
|
||||||
|
{
|
||||||
|
if (mTargetWindow && mTargetWindow != mPendingWindow) {
|
||||||
|
mTargetWindow->OnDragLeave();
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is possible that the pending state has been updated during dispatch
|
||||||
|
// of the leave event. That's fine.
|
||||||
|
|
||||||
|
// Now we collect the pending state because, from this point on, we want
|
||||||
|
// to use the same state for all events dispatched. All state is updated
|
||||||
|
// so that when other tasks are scheduled during dispatch here, this
|
||||||
|
// task is considered to have already been run.
|
||||||
|
bool positionHasChanged =
|
||||||
|
mPendingWindow != mTargetWindow ||
|
||||||
|
mPendingWindowPoint != mTargetWindowPoint;
|
||||||
|
DragTask task = mScheduledTask;
|
||||||
|
mScheduledTask = eDragTaskNone;
|
||||||
|
mTargetWindow = mPendingWindow.forget();
|
||||||
|
mTargetWindowPoint = mPendingWindowPoint;
|
||||||
|
|
||||||
|
if (task == eDragTaskLeave) {
|
||||||
|
// Nothing more to do
|
||||||
|
// Returning false removes the task source from the event loop.
|
||||||
|
mTaskSource = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This may be the start of a destination drag session.
|
||||||
|
StartDragSession();
|
||||||
|
|
||||||
|
// mTargetWidget may be NULL if the window has been destroyed.
|
||||||
|
// (The leave event is not scheduled if a drop task is still scheduled.)
|
||||||
|
// We still reply appropriately to indicate that the drop will or didn't
|
||||||
|
// succeeed.
|
||||||
|
mTargetWidget = mTargetWindow->GetMozContainerWidget();
|
||||||
|
mTargetDragContext.steal(mPendingDragContext);
|
||||||
|
mTargetTime = mPendingTime;
|
||||||
|
|
||||||
|
// http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model
|
||||||
|
// (as at 27 December 2010) indicates that a "drop" event should only be
|
||||||
|
// fired (at the current target element) if the current drag operation is
|
||||||
|
// not none. The current drag operation will only be set to a non-none
|
||||||
|
// value during a "dragover" event.
|
||||||
|
//
|
||||||
|
// If the user has ended the drag before any dragover events have been
|
||||||
|
// sent, then the spec recommends skipping the drop (because the current
|
||||||
|
// drag operation is none). However, here we assume that, by releasing
|
||||||
|
// the mouse button, the user has indicated that they want to drop, so we
|
||||||
|
// proceed with the drop where possible.
|
||||||
|
//
|
||||||
|
// In order to make the events appear to content in the same way as if the
|
||||||
|
// spec is being followed we make sure to dispatch a "dragover" event with
|
||||||
|
// appropriate coordinates and check canDrop before the "drop" event.
|
||||||
|
//
|
||||||
|
// When the Xdnd protocol is used for source/destination communication (as
|
||||||
|
// should be the case with GTK source applications) a dragover event
|
||||||
|
// should have already been sent during the drag-motion signal, which
|
||||||
|
// would have already been received because XdndDrop messages do not
|
||||||
|
// contain a position. However, we can't assume the same when the Motif
|
||||||
|
// protocol is used.
|
||||||
|
if (task == eDragTaskMotion || positionHasChanged) {
|
||||||
|
nsWindow::UpdateDragStatus(mTargetDragContext, this);
|
||||||
|
mTargetWindow->
|
||||||
|
DispatchDragMotionEvents(this, mTargetWindowPoint, mTargetTime);
|
||||||
|
|
||||||
|
if (task == eDragTaskMotion) {
|
||||||
|
// Reply to tell the source whether we can drop and what
|
||||||
|
// action would be taken.
|
||||||
|
TargetEndDragMotion(mTargetWidget, mTargetDragContext, mTargetTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task == eDragTaskDrop) {
|
||||||
|
gboolean success = mTargetWindow->
|
||||||
|
DispatchDragDropEvent(this, mTargetWindowPoint, mTargetTime);
|
||||||
|
|
||||||
|
// Perhaps we should set the del parameter to TRUE when the drag
|
||||||
|
// action is move, but we don't know whether the data was successfully
|
||||||
|
// transferred.
|
||||||
|
gtk_drag_finish(mTargetDragContext, success,
|
||||||
|
/* del = */ FALSE, mTargetTime);
|
||||||
|
|
||||||
|
// This drag is over, so clear out our reference to the previous
|
||||||
|
// window.
|
||||||
|
mTargetWindow = nsnull;
|
||||||
|
// Make sure to end the drag session. If this drag started in a
|
||||||
|
// different app, we won't get a drag_end signal to end it from.
|
||||||
|
EndDragSession(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're done with the drag context.
|
||||||
|
mTargetWidget = NULL;
|
||||||
|
mTargetDragContext = NULL;
|
||||||
|
|
||||||
|
// If we got another drag signal while running the sheduled task, that
|
||||||
|
// must have happened while running a nested event loop. Leave the task
|
||||||
|
// source on the event loop.
|
||||||
|
if (mScheduledTask != eDragTaskNone)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
// We have no task scheduled.
|
||||||
|
// Returning false removes the task source from the event loop.
|
||||||
|
mTaskSource = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
@ -46,6 +46,30 @@
|
|||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
class nsWindow;
|
||||||
|
|
||||||
|
#ifndef HAVE_NSGOBJECTREFTRAITS
|
||||||
|
#define HAVE_NSGOBJECTREFTRAITS
|
||||||
|
template <class T>
|
||||||
|
class nsGObjectRefTraits : public nsPointerRefTraits<T> {
|
||||||
|
public:
|
||||||
|
static void Release(T *aPtr) { g_object_unref(aPtr); }
|
||||||
|
static void AddRef(T *aPtr) { g_object_ref(aPtr); }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_NSAUTOREFTRAITS_GTKWIDGET
|
||||||
|
#define HAVE_NSAUTOREFTRAITS_GTKWIDGET
|
||||||
|
template <>
|
||||||
|
class nsAutoRefTraits<GtkWidget> : public nsGObjectRefTraits<GtkWidget> { };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_NSAUTOREFTRAITS_GDKDRAGCONTEXT
|
||||||
|
#define HAVE_NSAUTOREFTRAITS_GDKDRAGCONTEXT
|
||||||
|
template <>
|
||||||
|
class nsAutoRefTraits<GdkDragContext> :
|
||||||
|
public nsGObjectRefTraits<GdkDragContext> { };
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Native GTK DragService wrapper
|
* Native GTK DragService wrapper
|
||||||
@ -100,6 +124,25 @@ public:
|
|||||||
|
|
||||||
static nsDragService* GetInstance();
|
static nsDragService* GetInstance();
|
||||||
|
|
||||||
|
// Methods called from nsWindow to handle responding to GTK drag
|
||||||
|
// destination signals
|
||||||
|
|
||||||
|
gboolean ScheduleMotionEvent(nsWindow *aWindow,
|
||||||
|
GdkDragContext *aDragContext,
|
||||||
|
nsIntPoint aWindowPoint,
|
||||||
|
guint aTime);
|
||||||
|
void ScheduleLeaveEvent();
|
||||||
|
gboolean ScheduleDropEvent(nsWindow *aWindow,
|
||||||
|
GdkDragContext *aDragContext,
|
||||||
|
nsIntPoint aWindowPoint,
|
||||||
|
guint aTime);
|
||||||
|
|
||||||
|
nsWindow* GetMostRecentDestWindow()
|
||||||
|
{
|
||||||
|
return mScheduledTask == eDragTaskNone ? mTargetWindow
|
||||||
|
: mPendingWindow;
|
||||||
|
}
|
||||||
|
|
||||||
// END PUBLIC API
|
// END PUBLIC API
|
||||||
|
|
||||||
// These methods are public only so that they can be called from functions
|
// These methods are public only so that they can be called from functions
|
||||||
@ -118,14 +161,47 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// target side vars
|
// mScheduledTask indicates what signal has been received from GTK and
|
||||||
|
// so what needs to be dispatched when the scheduled task is run. It is
|
||||||
|
// eDragTaskNone when there is no task scheduled (but the
|
||||||
|
// previous task may still not have finished running).
|
||||||
|
enum DragTask {
|
||||||
|
eDragTaskNone,
|
||||||
|
eDragTaskMotion,
|
||||||
|
eDragTaskLeave,
|
||||||
|
eDragTaskDrop
|
||||||
|
};
|
||||||
|
DragTask mScheduledTask;
|
||||||
|
// mTaskSource is the GSource id for the task that is either scheduled
|
||||||
|
// or currently running. It is 0 if no task is scheduled or running.
|
||||||
|
guint mTaskSource;
|
||||||
|
|
||||||
// the last widget that was the target of a drag
|
// target/destination side vars
|
||||||
GtkWidget *mTargetWidget;
|
// These variables keep track of the state of the current drag.
|
||||||
GdkDragContext *mTargetDragContext;
|
|
||||||
|
// mPendingWindow, mPendingWindowPoint, mPendingDragContext, and
|
||||||
|
// mPendingTime, carry information from the GTK signal that will be used
|
||||||
|
// when the scheduled task is run. mPendingWindow and mPendingDragContext
|
||||||
|
// will be NULL if the scheduled task is eDragTaskLeave.
|
||||||
|
nsRefPtr<nsWindow> mPendingWindow;
|
||||||
|
nsIntPoint mPendingWindowPoint;
|
||||||
|
nsCountedRef<GdkDragContext> mPendingDragContext;
|
||||||
|
guint mPendingTime;
|
||||||
|
|
||||||
|
// mTargetWindow and mTargetWindowPoint record the position of the last
|
||||||
|
// eDragTaskMotion or eDragTaskDrop task that was run or is still running.
|
||||||
|
// mTargetWindow is cleared once the drag has completed or left.
|
||||||
|
nsRefPtr<nsWindow> mTargetWindow;
|
||||||
|
nsIntPoint mTargetWindowPoint;
|
||||||
|
// mTargetWidget and mTargetDragContext are set only while dispatching
|
||||||
|
// motion or drop events. mTime records the corresponding timestamp.
|
||||||
|
nsCountedRef<GtkWidget> mTargetWidget;
|
||||||
|
nsCountedRef<GdkDragContext> mTargetDragContext;
|
||||||
guint mTargetTime;
|
guint mTargetTime;
|
||||||
|
|
||||||
// is it OK to drop on us?
|
// is it OK to drop on us?
|
||||||
bool mCanDrop;
|
bool mCanDrop;
|
||||||
|
|
||||||
// have we received our drag data?
|
// have we received our drag data?
|
||||||
bool mTargetDragDataReceived;
|
bool mTargetDragDataReceived;
|
||||||
// last data received and its length
|
// last data received and its length
|
||||||
@ -161,6 +237,13 @@ private:
|
|||||||
PRInt32 aYOffset,
|
PRInt32 aYOffset,
|
||||||
const nsIntRect &dragRect);
|
const nsIntRect &dragRect);
|
||||||
|
|
||||||
|
gboolean Schedule(DragTask aTask, nsWindow *aWindow,
|
||||||
|
GdkDragContext *aDragContext,
|
||||||
|
nsIntPoint aWindowPoint, guint aTime);
|
||||||
|
|
||||||
|
// Callback for g_idle_add_full() to run mScheduledTask.
|
||||||
|
static gboolean TaskDispatchCallback(gpointer data);
|
||||||
|
gboolean RunScheduledTask();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsDragService_h__
|
#endif // nsDragService_h__
|
||||||
|
@ -272,9 +272,6 @@ static void drag_data_received_event_cb(GtkWidget *aWidget,
|
|||||||
/* initialization static functions */
|
/* initialization static functions */
|
||||||
static nsresult initialize_prefs (void);
|
static nsresult initialize_prefs (void);
|
||||||
|
|
||||||
// this is the last window that had a drag event happen on it.
|
|
||||||
nsWindow *nsWindow::sLastDragMotionWindow = NULL;
|
|
||||||
|
|
||||||
// Time of the last button release event. We use it to detect when the
|
// Time of the last button release event. We use it to detect when the
|
||||||
// drag ended before we could properly setup drag and drop.
|
// drag ended before we could properly setup drag and drop.
|
||||||
static guint32 sLastButtonReleaseTime = 0;
|
static guint32 sLastButtonReleaseTime = 0;
|
||||||
@ -433,9 +430,6 @@ nsWindow::nsWindow()
|
|||||||
nsWindow::~nsWindow()
|
nsWindow::~nsWindow()
|
||||||
{
|
{
|
||||||
LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this));
|
LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this));
|
||||||
if (sLastDragMotionWindow == this) {
|
|
||||||
sLastDragMotionWindow = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] mTransparencyBitmap;
|
delete[] mTransparencyBitmap;
|
||||||
mTransparencyBitmap = nsnull;
|
mTransparencyBitmap = nsnull;
|
||||||
@ -687,6 +681,11 @@ nsWindow::Destroy(void)
|
|||||||
gRollupListener = nsnull;
|
gRollupListener = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsDragService *dragService = nsDragService::GetInstance();
|
||||||
|
if (this == dragService->GetMostRecentDestWindow()) {
|
||||||
|
dragService->ScheduleLeaveEvent();
|
||||||
|
}
|
||||||
|
|
||||||
NativeShow(false);
|
NativeShow(false);
|
||||||
|
|
||||||
if (mIMModule) {
|
if (mIMModule) {
|
||||||
@ -715,11 +714,6 @@ nsWindow::Destroy(void)
|
|||||||
// the surface after its X Window.
|
// the surface after its X Window.
|
||||||
mThebesSurface = nsnull;
|
mThebesSurface = nsnull;
|
||||||
|
|
||||||
if (mDragLeaveTimer) {
|
|
||||||
mDragLeaveTimer->Cancel();
|
|
||||||
mDragLeaveTimer = nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkWidget *owningWidget = GetMozContainerWidget();
|
GtkWidget *owningWidget = GetMozContainerWidget();
|
||||||
if (mShell) {
|
if (mShell) {
|
||||||
gtk_widget_destroy(mShell);
|
gtk_widget_destroy(mShell);
|
||||||
@ -3309,35 +3303,6 @@ nsWindow::ThemeChanged()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsWindow::CheckNeedDragLeave(nsWindow* aInnerMostWidget,
|
|
||||||
nsIDragService* aDragService,
|
|
||||||
GdkDragContext *aDragContext,
|
|
||||||
nscoord aX, nscoord aY)
|
|
||||||
{
|
|
||||||
// check to see if there was a drag motion window already in place
|
|
||||||
if (sLastDragMotionWindow) {
|
|
||||||
// same as the last window so no need for dragleave event
|
|
||||||
if (sLastDragMotionWindow == aInnerMostWidget) {
|
|
||||||
UpdateDragStatus(aDragContext, aDragService);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send a dragleave event to the last window that got a motion event
|
|
||||||
nsRefPtr<nsWindow> kungFuDeathGrip = sLastDragMotionWindow;
|
|
||||||
sLastDragMotionWindow->OnDragLeave();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that the drag service knows we're now dragging
|
|
||||||
aDragService->StartDragSession();
|
|
||||||
|
|
||||||
// update our drag status
|
|
||||||
UpdateDragStatus(aDragContext, aDragService);
|
|
||||||
|
|
||||||
// set the last window to the innerMostWidget
|
|
||||||
sLastDragMotionWindow = aInnerMostWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWindow::DispatchDragMotionEvents(nsDragService *aDragService,
|
nsWindow::DispatchDragMotionEvents(nsDragService *aDragService,
|
||||||
const nsIntPoint& aWindowPoint, guint aTime)
|
const nsIntPoint& aWindowPoint, guint aTime)
|
||||||
@ -3386,170 +3351,6 @@ nsWindow::DispatchDragEvent(PRUint32 aMsg, const nsIntPoint& aRefPoint,
|
|||||||
DispatchEvent(&event, status);
|
DispatchEvent(&event, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
|
||||||
nsWindow::OnDragMotionEvent(GtkWidget *aWidget,
|
|
||||||
GdkDragContext *aDragContext,
|
|
||||||
gint aX,
|
|
||||||
gint aY,
|
|
||||||
guint aTime,
|
|
||||||
gpointer aData)
|
|
||||||
{
|
|
||||||
LOGDRAG(("nsWindow::OnDragMotionSignal\n"));
|
|
||||||
|
|
||||||
// get our drag context
|
|
||||||
nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
|
|
||||||
nsDragService *dragServiceGTK =
|
|
||||||
static_cast<nsDragService*>(dragService.get());
|
|
||||||
|
|
||||||
// first, figure out which internal widget this drag motion actually
|
|
||||||
// happened on
|
|
||||||
nscoord retx = 0;
|
|
||||||
nscoord rety = 0;
|
|
||||||
|
|
||||||
GdkWindow *innerWindow = get_inner_gdk_window(gtk_widget_get_window(aWidget), aX, aY,
|
|
||||||
&retx, &rety);
|
|
||||||
nsRefPtr<nsWindow> innerMostWidget = get_window_for_gdk_window(innerWindow);
|
|
||||||
|
|
||||||
if (!innerMostWidget)
|
|
||||||
innerMostWidget = this;
|
|
||||||
|
|
||||||
// clear any drag leave timer that might be pending so that it
|
|
||||||
// doesn't get processed when we actually go out to get data.
|
|
||||||
if (mDragLeaveTimer) {
|
|
||||||
mDragLeaveTimer->Cancel();
|
|
||||||
mDragLeaveTimer = nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckNeedDragLeave(innerMostWidget, dragService, aDragContext, retx, rety);
|
|
||||||
|
|
||||||
// update the drag context
|
|
||||||
dragServiceGTK->TargetSetLastContext(aWidget, aDragContext, aTime);
|
|
||||||
|
|
||||||
innerMostWidget->
|
|
||||||
DispatchDragMotionEvents(dragServiceGTK, nsIntPoint(retx, rety), aTime);
|
|
||||||
|
|
||||||
// Reply to tell the source whether we can drop and what action would be
|
|
||||||
// taken.
|
|
||||||
dragServiceGTK->TargetEndDragMotion(aWidget, aDragContext, aTime);
|
|
||||||
|
|
||||||
// and unset our context
|
|
||||||
dragServiceGTK->TargetSetLastContext(0, 0, 0);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsWindow::OnDragLeaveEvent(GtkWidget *aWidget,
|
|
||||||
GdkDragContext *aDragContext,
|
|
||||||
guint aTime,
|
|
||||||
gpointer aData)
|
|
||||||
{
|
|
||||||
// XXX Do we want to pass this on only if the event's subwindow is null?
|
|
||||||
|
|
||||||
LOGDRAG(("nsWindow::OnDragLeaveSignal(%p)\n", (void*)this));
|
|
||||||
|
|
||||||
if (mDragLeaveTimer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a fast timer - we're delaying the drag leave until the
|
|
||||||
// next mainloop in hopes that we might be able to get a drag drop
|
|
||||||
// signal
|
|
||||||
mDragLeaveTimer = do_CreateInstance("@mozilla.org/timer;1");
|
|
||||||
NS_ASSERTION(mDragLeaveTimer, "Failed to create drag leave timer!");
|
|
||||||
// fire this baby asafp, but not too quickly... see bug 216800 ;-)
|
|
||||||
mDragLeaveTimer->InitWithFuncCallback(DragLeaveTimerCallback,
|
|
||||||
(void *)this,
|
|
||||||
20, nsITimer::TYPE_ONE_SHOT);
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
nsWindow::OnDragDropEvent(GtkWidget *aWidget,
|
|
||||||
GdkDragContext *aDragContext,
|
|
||||||
gint aX,
|
|
||||||
gint aY,
|
|
||||||
guint aTime,
|
|
||||||
gpointer aData)
|
|
||||||
|
|
||||||
{
|
|
||||||
LOGDRAG(("nsWindow::OnDragDropSignal\n"));
|
|
||||||
|
|
||||||
// get our drag context
|
|
||||||
nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
|
|
||||||
nsDragService *dragServiceGTK = static_cast<nsDragService*>(dragService.get());
|
|
||||||
|
|
||||||
dragServiceGTK->SetDragEndPoint(nsIntPoint(aX, aY) + WidgetToScreenOffset());
|
|
||||||
|
|
||||||
nscoord retx = 0;
|
|
||||||
nscoord rety = 0;
|
|
||||||
|
|
||||||
GdkWindow *innerWindow = get_inner_gdk_window(gtk_widget_get_window(aWidget), aX, aY,
|
|
||||||
&retx, &rety);
|
|
||||||
nsRefPtr<nsWindow> innerMostWidget = get_window_for_gdk_window(innerWindow);
|
|
||||||
|
|
||||||
if (!innerMostWidget)
|
|
||||||
innerMostWidget = this;
|
|
||||||
|
|
||||||
// clear any drag leave timer that might be pending so that it
|
|
||||||
// doesn't get processed when we actually go out to get data.
|
|
||||||
if (mDragLeaveTimer) {
|
|
||||||
mDragLeaveTimer->Cancel();
|
|
||||||
mDragLeaveTimer = nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckNeedDragLeave(innerMostWidget, dragService, aDragContext, retx, rety);
|
|
||||||
|
|
||||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-and-drop-processing-model
|
|
||||||
// (as at 27 December 2010) indicates that a "drop" event should only be
|
|
||||||
// fired (at the current target element) if the current drag operation is
|
|
||||||
// not none. The current drag operation will only be set to a non-none
|
|
||||||
// value during a "dragover" event.
|
|
||||||
//
|
|
||||||
// If the user has ended the drag before any dragover events have been
|
|
||||||
// sent, then the spec recommends skipping the drop (because the current
|
|
||||||
// drag operation is none). However, here we assume that, by releasing
|
|
||||||
// the mouse button, the user has indicated that they want to drop, so we
|
|
||||||
// proceed with the drop where possible.
|
|
||||||
//
|
|
||||||
// In order to make the events appear to content in the same way as if the
|
|
||||||
// spec is being followed we make sure to dispatch a "dragover" event with
|
|
||||||
// appropriate coordinates and check canDrop before the "drop" event.
|
|
||||||
//
|
|
||||||
// When the Xdnd protocol is used for source/destination communication (as
|
|
||||||
// should be the case with GTK source applications) a dragover event
|
|
||||||
// should have already been sent during the drag-motion signal, which
|
|
||||||
// would have already been received because XdndDrop messages do not
|
|
||||||
// contain a position. However, we can't assume the same when the Motif
|
|
||||||
// protocol is used.
|
|
||||||
|
|
||||||
dragServiceGTK->TargetSetLastContext(aWidget, aDragContext, aTime);
|
|
||||||
|
|
||||||
innerMostWidget->
|
|
||||||
DispatchDragMotionEvents(dragServiceGTK, nsIntPoint(retx, rety), aTime);
|
|
||||||
|
|
||||||
gboolean success = innerMostWidget->
|
|
||||||
DispatchDragDropEvent(dragServiceGTK, nsIntPoint(retx, rety), aTime);
|
|
||||||
|
|
||||||
// before we unset the context we need to do a drop_finish
|
|
||||||
|
|
||||||
gdk_drop_finish(aDragContext, success, aTime);
|
|
||||||
|
|
||||||
// after a drop takes place we need to make sure that the drag
|
|
||||||
// service doesn't think that it still has a context. if the other
|
|
||||||
// way ( besides the drop ) to end a drag event is during the leave
|
|
||||||
// event and and that case is handled in that handler.
|
|
||||||
dragServiceGTK->TargetSetLastContext(0, 0, 0);
|
|
||||||
|
|
||||||
// clear the sLastDragMotion window
|
|
||||||
sLastDragMotionWindow = 0;
|
|
||||||
|
|
||||||
// Make sure to end the drag session. If this drag started in a
|
|
||||||
// different app, we won't get a drag_end signal to end it from.
|
|
||||||
dragService->EndDragSession(true);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWindow::OnDragDataReceivedEvent(GtkWidget *aWidget,
|
nsWindow::OnDragDataReceivedEvent(GtkWidget *aWidget,
|
||||||
GdkDragContext *aDragContext,
|
GdkDragContext *aDragContext,
|
||||||
@ -5910,7 +5711,7 @@ nsWindow::InitDragEvent(nsDragEvent &aEvent)
|
|||||||
// drag context. Gtk gets this from a combination of the key settings
|
// drag context. Gtk gets this from a combination of the key settings
|
||||||
// and what the source is offering.
|
// and what the source is offering.
|
||||||
|
|
||||||
void
|
/* static */ void
|
||||||
nsWindow::UpdateDragStatus(GdkDragContext *aDragContext,
|
nsWindow::UpdateDragStatus(GdkDragContext *aDragContext,
|
||||||
nsIDragService *aDragService)
|
nsIDragService *aDragService)
|
||||||
{
|
{
|
||||||
@ -5973,9 +5774,24 @@ drag_motion_event_cb(GtkWidget *aWidget,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return window->OnDragMotionEvent(aWidget,
|
// figure out which internal widget this drag motion actually happened on
|
||||||
aDragContext,
|
nscoord retx = 0;
|
||||||
aX, aY, aTime, aData);
|
nscoord rety = 0;
|
||||||
|
|
||||||
|
GdkWindow *innerWindow =
|
||||||
|
get_inner_gdk_window(gtk_widget_get_window(aWidget), aX, aY,
|
||||||
|
&retx, &rety);
|
||||||
|
nsRefPtr<nsWindow> innerMostWindow = get_window_for_gdk_window(innerWindow);
|
||||||
|
|
||||||
|
if (!innerMostWindow) {
|
||||||
|
innerMostWindow = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGDRAG(("nsWindow drag-motion signal for %p\n", (void*)innerMostWindow));
|
||||||
|
|
||||||
|
return nsDragService::GetInstance()->
|
||||||
|
ScheduleMotionEvent(innerMostWindow, aDragContext,
|
||||||
|
nsIntPoint(aX, aY), aTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -5988,7 +5804,27 @@ drag_leave_event_cb(GtkWidget *aWidget,
|
|||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window->OnDragLeaveEvent(aWidget, aDragContext, aTime, aData);
|
nsDragService *dragService = nsDragService::GetInstance();
|
||||||
|
|
||||||
|
nsWindow *mostRecentDragWindow = dragService->GetMostRecentDestWindow();
|
||||||
|
if (!mostRecentDragWindow) {
|
||||||
|
NS_WARNING("Spurious drag leave signal");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *mozContainer = mostRecentDragWindow->GetMozContainerWidget();
|
||||||
|
if (aWidget != mozContainer)
|
||||||
|
{
|
||||||
|
// When the drag moves between widgets, GTK can send leave signal for
|
||||||
|
// the old widget after the motion or drop signal for the new widget.
|
||||||
|
// We'll send the leave event when the motion or drop event is run.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGDRAG(("nsWindow drag-leave signal for %p\n",
|
||||||
|
(void*)mostRecentDragWindow));
|
||||||
|
|
||||||
|
dragService->ScheduleLeaveEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6004,9 +5840,24 @@ drag_drop_event_cb(GtkWidget *aWidget,
|
|||||||
if (!window)
|
if (!window)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return window->OnDragDropEvent(aWidget,
|
// figure out which internal widget this drag motion actually happened on
|
||||||
aDragContext,
|
nscoord retx = 0;
|
||||||
aX, aY, aTime, aData);
|
nscoord rety = 0;
|
||||||
|
|
||||||
|
GdkWindow *innerWindow =
|
||||||
|
get_inner_gdk_window(gtk_widget_get_window(aWidget), aX, aY,
|
||||||
|
&retx, &rety);
|
||||||
|
nsRefPtr<nsWindow> innerMostWindow = get_window_for_gdk_window(innerWindow);
|
||||||
|
|
||||||
|
if (!innerMostWindow) {
|
||||||
|
innerMostWindow = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGDRAG(("nsWindow drag-drop signal for %p\n", (void*)innerMostWindow));
|
||||||
|
|
||||||
|
return nsDragService::GetInstance()->
|
||||||
|
ScheduleDropEvent(innerMostWindow, aDragContext,
|
||||||
|
nsIntPoint(aX, aY), aTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -6041,30 +5892,6 @@ initialize_prefs(void)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsWindow::FireDragLeaveTimer(void)
|
|
||||||
{
|
|
||||||
LOGDRAG(("nsWindow::FireDragLeaveTimer(%p)\n", (void*)this));
|
|
||||||
|
|
||||||
mDragLeaveTimer = nsnull;
|
|
||||||
|
|
||||||
// clean up any pending drag motion window info
|
|
||||||
if (sLastDragMotionWindow) {
|
|
||||||
nsRefPtr<nsWindow> kungFuDeathGrip = sLastDragMotionWindow;
|
|
||||||
// send our leave signal
|
|
||||||
sLastDragMotionWindow->OnDragLeave();
|
|
||||||
sLastDragMotionWindow = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
void
|
|
||||||
nsWindow::DragLeaveTimerCallback(nsITimer *aTimer, void *aClosure)
|
|
||||||
{
|
|
||||||
nsRefPtr<nsWindow> window = static_cast<nsWindow *>(aClosure);
|
|
||||||
window->FireDragLeaveTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
static GdkWindow *
|
static GdkWindow *
|
||||||
get_inner_gdk_window (GdkWindow *aWindow,
|
get_inner_gdk_window (GdkWindow *aWindow,
|
||||||
gint x, gint y,
|
gint x, gint y,
|
||||||
|
@ -237,22 +237,6 @@ public:
|
|||||||
GdkEventVisibility *aEvent);
|
GdkEventVisibility *aEvent);
|
||||||
void OnWindowStateEvent(GtkWidget *aWidget,
|
void OnWindowStateEvent(GtkWidget *aWidget,
|
||||||
GdkEventWindowState *aEvent);
|
GdkEventWindowState *aEvent);
|
||||||
gboolean OnDragMotionEvent(GtkWidget *aWidget,
|
|
||||||
GdkDragContext *aDragContext,
|
|
||||||
gint aX,
|
|
||||||
gint aY,
|
|
||||||
guint aTime,
|
|
||||||
gpointer aData);
|
|
||||||
void OnDragLeaveEvent(GtkWidget * aWidget,
|
|
||||||
GdkDragContext *aDragContext,
|
|
||||||
guint aTime,
|
|
||||||
gpointer aData);
|
|
||||||
gboolean OnDragDropEvent(GtkWidget *aWidget,
|
|
||||||
GdkDragContext *aDragContext,
|
|
||||||
gint aX,
|
|
||||||
gint aY,
|
|
||||||
guint aTime,
|
|
||||||
gpointer aData);
|
|
||||||
void OnDragDataReceivedEvent(GtkWidget *aWidget,
|
void OnDragDataReceivedEvent(GtkWidget *aWidget,
|
||||||
GdkDragContext *aDragContext,
|
GdkDragContext *aDragContext,
|
||||||
gint aX,
|
gint aX,
|
||||||
@ -297,11 +281,6 @@ public:
|
|||||||
|
|
||||||
void ThemeChanged(void);
|
void ThemeChanged(void);
|
||||||
|
|
||||||
void CheckNeedDragLeave(nsWindow* aInnerMostWidget,
|
|
||||||
nsIDragService* aDragService,
|
|
||||||
GdkDragContext *aDragContext,
|
|
||||||
nscoord aX, nscoord aY);
|
|
||||||
|
|
||||||
#ifdef MOZ_X11
|
#ifdef MOZ_X11
|
||||||
Window mOldFocusWindow;
|
Window mOldFocusWindow;
|
||||||
#endif /* MOZ_X11 */
|
#endif /* MOZ_X11 */
|
||||||
@ -312,6 +291,9 @@ public:
|
|||||||
NS_IMETHOD BeginMoveDrag(nsMouseEvent* aEvent);
|
NS_IMETHOD BeginMoveDrag(nsMouseEvent* aEvent);
|
||||||
|
|
||||||
MozContainer* GetMozContainer() { return mContainer; }
|
MozContainer* GetMozContainer() { return mContainer; }
|
||||||
|
// GetMozContainerWidget returns the MozContainer even for undestroyed
|
||||||
|
// descendant windows
|
||||||
|
GtkWidget* GetMozContainerWidget();
|
||||||
GdkWindow* GetGdkWindow() { return mGdkWindow; }
|
GdkWindow* GetGdkWindow() { return mGdkWindow; }
|
||||||
bool IsDestroyed() { return mIsDestroyed; }
|
bool IsDestroyed() { return mIsDestroyed; }
|
||||||
|
|
||||||
@ -324,6 +306,8 @@ public:
|
|||||||
gboolean DispatchDragDropEvent(nsDragService *aDragService,
|
gboolean DispatchDragDropEvent(nsDragService *aDragService,
|
||||||
const nsIntPoint& aWindowPoint,
|
const nsIntPoint& aWindowPoint,
|
||||||
guint aTime);
|
guint aTime);
|
||||||
|
static void UpdateDragStatus (GdkDragContext *aDragContext,
|
||||||
|
nsIDragService *aDragService);
|
||||||
// If this dispatched the keydown event actually, this returns TRUE,
|
// If this dispatched the keydown event actually, this returns TRUE,
|
||||||
// otherwise, FALSE.
|
// otherwise, FALSE.
|
||||||
bool DispatchKeyDownEvent(GdkEventKey *aEvent,
|
bool DispatchKeyDownEvent(GdkEventKey *aEvent,
|
||||||
@ -393,7 +377,6 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void DestroyChildWindows();
|
void DestroyChildWindows();
|
||||||
void GetToplevelWidget(GtkWidget **aWidget);
|
void GetToplevelWidget(GtkWidget **aWidget);
|
||||||
GtkWidget *GetMozContainerWidget();
|
|
||||||
nsWindow *GetContainerWindow();
|
nsWindow *GetContainerWindow();
|
||||||
void SetUrgencyHint(GtkWidget *top_window, bool state);
|
void SetUrgencyHint(GtkWidget *top_window, bool state);
|
||||||
void *SetupPluginPort(void);
|
void *SetupPluginPort(void);
|
||||||
@ -493,13 +476,8 @@ private:
|
|||||||
gchar* mTransparencyBitmap;
|
gchar* mTransparencyBitmap;
|
||||||
|
|
||||||
// all of our DND stuff
|
// all of our DND stuff
|
||||||
// this is the last window that had a drag event happen on it.
|
|
||||||
static nsWindow *sLastDragMotionWindow;
|
|
||||||
void InitDragEvent (nsDragEvent &aEvent);
|
void InitDragEvent (nsDragEvent &aEvent);
|
||||||
void UpdateDragStatus (GdkDragContext *aDragContext,
|
|
||||||
nsIDragService *aDragService);
|
|
||||||
|
|
||||||
nsCOMPtr<nsITimer> mDragLeaveTimer;
|
|
||||||
float mLastMotionPressure;
|
float mLastMotionPressure;
|
||||||
|
|
||||||
// Remember the last sizemode so that we can restore it when
|
// Remember the last sizemode so that we can restore it when
|
||||||
@ -508,9 +486,6 @@ private:
|
|||||||
|
|
||||||
static bool DragInProgress(void);
|
static bool DragInProgress(void);
|
||||||
|
|
||||||
void FireDragLeaveTimer (void);
|
|
||||||
static void DragLeaveTimerCallback (nsITimer *aTimer, void *aClosure);
|
|
||||||
|
|
||||||
void DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent);
|
void DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user