зеркало из https://github.com/mozilla/gecko-dev.git
This commit is contained in:
Родитель
f5f0344430
Коммит
c616ebd613
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
typedef void (*nsIDragSessionGTKTimeCB)(guint32 *aTime);
|
||||
|
||||
#define NS_IDRAGSESSIONGTK_IID \
|
||||
{ 0xa6b49c42, 0x1dd1, 0x11b2, { 0xb2, 0xdf, 0xc1, 0xd6, 0x1d, 0x67, 0x45, 0xcf } };
|
||||
|
||||
|
@ -37,19 +39,23 @@ class nsIDragSessionGTK : public nsISupports {
|
|||
NS_IMETHOD SetLastContext (GtkWidget *aWidget,
|
||||
GdkDragContext *aContext,
|
||||
guint aTime) = 0;
|
||||
NS_IMETHOD UpdateDragStatus(GtkWidget *aWidget,
|
||||
GdkDragContext *aContext,
|
||||
guint aTime) = 0;
|
||||
NS_IMETHOD SetDataReceived (GtkWidget *aWidget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint32 time) = 0;
|
||||
guint32 aTime) = 0;
|
||||
NS_IMETHOD DataGetSignal (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint32 time,
|
||||
guint32 aTime,
|
||||
gpointer data) = 0;
|
||||
NS_IMETHOD SetTimeCallback (nsIDragSessionGTKTimeCB aCallback) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "nsPrimitiveHelpers.h"
|
||||
#include "nsString.h"
|
||||
#include <gtk/gtkinvisible.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
static NS_DEFINE_IID(kCDragServiceCID, NS_DRAGSERVICE_CID);
|
||||
|
||||
|
@ -71,6 +72,7 @@ nsDragService::nsDragService()
|
|||
mDoingDrag = PR_FALSE;
|
||||
// reset everything
|
||||
ResetDragState();
|
||||
mTimeCB = nsnull;
|
||||
}
|
||||
|
||||
nsDragService::~nsDragService()
|
||||
|
@ -84,6 +86,9 @@ NS_IMETHODIMP nsDragService::InvokeDragSession (nsISupportsArray * anArrayTransf
|
|||
nsIScriptableRegion * aRegion,
|
||||
PRUint32 aActionType)
|
||||
{
|
||||
#ifdef DEBUG_DD
|
||||
g_print("InvokeDragSession\n");
|
||||
#endif
|
||||
// make sure that we have an array of transferables to use
|
||||
if (!anArrayTransferables)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -96,12 +101,34 @@ NS_IMETHODIMP nsDragService::InvokeDragSession (nsISupportsArray * anArrayTransf
|
|||
// create a target list from the list of transferables
|
||||
GtkTargetList *targetList = targetListFromTransArr(anArrayTransferables);
|
||||
if (targetList) {
|
||||
// get the last time event. we do this because if we don't then
|
||||
// gdk_drag_begin() will use the current time as the arg for the
|
||||
// grab. if you happen to do a drag really quickly and release
|
||||
// the mouse button before the drag begins ( really easy to do, by
|
||||
// the way ) then the server ungrab from the mouse button release
|
||||
// will actually have a time that is _before_ the server grab that
|
||||
// we are about to cause and it will leave the server in a grabbed
|
||||
// state after the drag has ended.
|
||||
guint32 last_event_time = 0;
|
||||
mTimeCB(&last_event_time);
|
||||
// synth an event so that that fun bug in the gtk dnd code doesn't
|
||||
// rear its ugly head
|
||||
GdkEvent gdk_event;
|
||||
gdk_event.type = GDK_NOTHING;
|
||||
gdk_event.any.window = 0;
|
||||
gdk_event.any.send_event = 0;
|
||||
gdk_event.type = GDK_BUTTON_PRESS;
|
||||
gdk_event.button.window = mHiddenWidget->window;
|
||||
gdk_event.button.send_event = 0;
|
||||
gdk_event.button.time = last_event_time;
|
||||
gdk_event.button.x = 0;
|
||||
gdk_event.button.y = 0;
|
||||
gdk_event.button.pressure = 0;
|
||||
gdk_event.button.xtilt = 0;
|
||||
gdk_event.button.ytilt = 0;
|
||||
gdk_event.button.state = 0;
|
||||
gdk_event.button.button = 0;
|
||||
gdk_event.button.source = (GdkInputSource)0;
|
||||
gdk_event.button.deviceid = 0;
|
||||
gdk_event.button.x_root = 0;
|
||||
gdk_event.button.y_root = 0;
|
||||
|
||||
// start our drag.
|
||||
GdkDragContext *context = gtk_drag_begin(mHiddenWidget,
|
||||
|
@ -112,6 +139,8 @@ NS_IMETHODIMP nsDragService::InvokeDragSession (nsISupportsArray * anArrayTransf
|
|||
// make sure to set our default icon
|
||||
gtk_drag_set_icon_default (context);
|
||||
gtk_target_list_unref(targetList);
|
||||
// set our last context as this context
|
||||
SetLastContext(mHiddenWidget, context, gdk_time_get());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -129,7 +158,6 @@ NS_IMETHODIMP nsDragService::EndDragSession()
|
|||
{
|
||||
// a drag just ended. reset everything.
|
||||
ResetDragState();
|
||||
mDoingDrag = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -139,12 +167,6 @@ NS_IMETHODIMP nsDragService::SetCanDrop (PRBool aCanDrop)
|
|||
#ifdef DEBUG_DD
|
||||
g_print("can drop: %d\n", aCanDrop);
|
||||
#endif
|
||||
if (aCanDrop) {
|
||||
gdk_drag_status(mLastContext, GDK_ACTION_COPY, mLastTime);
|
||||
}
|
||||
else {
|
||||
gdk_drag_status(mLastContext, (GdkDragAction)0, mLastTime);
|
||||
}
|
||||
mCanDrop = aCanDrop;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -319,6 +341,20 @@ NS_IMETHODIMP nsDragService::SetLastContext (GtkWidget *aWidget,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDragService::UpdateDragStatus(GtkWidget *aWidget,
|
||||
GdkDragContext *aContext,
|
||||
guint aTime)
|
||||
{
|
||||
#ifdef DEBUG_DD
|
||||
g_print("UpdateDragStatus: %d\n", mCanDrop);
|
||||
#endif
|
||||
if (mCanDrop)
|
||||
gdk_drag_status(aContext, GDK_ACTION_COPY, aTime);
|
||||
else
|
||||
gdk_drag_status(aContext, (GdkDragAction)0, mLastTime);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDragService::SetDataReceived (GtkWidget *aWidget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
|
@ -424,6 +460,15 @@ NS_IMETHODIMP nsDragService::DataGetSignal (GtkWidget *widget,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDragService::SetTimeCallback (nsIDragSessionGTKTimeCB aCallback)
|
||||
{
|
||||
#ifdef DEBUG_DD
|
||||
g_print("SetTimeCallback %p\n", aCallback);
|
||||
#endif
|
||||
mTimeCB = aCallback;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsDragService::ResetDragState(void)
|
||||
{
|
||||
// make sure that all of our last state is set
|
||||
|
@ -440,6 +485,8 @@ void nsDragService::ResetDragState(void)
|
|||
mDragData = NULL;
|
||||
}
|
||||
mDragDataLen = 0;
|
||||
mCanDrop = PR_FALSE;
|
||||
mDoingDrag = PR_FALSE;
|
||||
}
|
||||
|
||||
void nsDragService::SetDataItems(nsISupportsArray *anArray)
|
||||
|
@ -475,10 +522,6 @@ static void invisibleDragEnd (GtkWidget *widget,
|
|||
// apparently, the drag is over. make sure to tell the drag service
|
||||
// about it.
|
||||
nsCOMPtr<nsIDragService> dragService;
|
||||
|
||||
gdk_pointer_ungrab(GDK_CURRENT_TIME);
|
||||
gdk_keyboard_ungrab(GDK_CURRENT_TIME);
|
||||
|
||||
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
|
||||
NS_GET_IID(nsIDragService),
|
||||
(nsISupports **)&dragService);
|
||||
|
|
|
@ -59,6 +59,9 @@ public:
|
|||
NS_IMETHOD SetLastContext (GtkWidget *aWidget,
|
||||
GdkDragContext *aContext,
|
||||
guint aTime);
|
||||
NS_IMETHOD UpdateDragStatus(GtkWidget *aWidget,
|
||||
GdkDragContext *aContext,
|
||||
guint aTime);
|
||||
NS_IMETHOD SetDataReceived (GtkWidget *aWidget,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
|
@ -72,6 +75,7 @@ public:
|
|||
guint info,
|
||||
guint32 time,
|
||||
gpointer data);
|
||||
NS_IMETHOD SetTimeCallback (nsIDragSessionGTKTimeCB aCallback);
|
||||
|
||||
// END PUBLIC API
|
||||
|
||||
|
@ -103,6 +107,9 @@ private:
|
|||
void SetDataItems(nsISupportsArray *anArray);
|
||||
// get the data for a particular flavor
|
||||
NS_METHOD GetNativeDragData(GdkAtom aFlavor);
|
||||
// this is a callback to get the time for the last event that
|
||||
// happened
|
||||
nsIDragSessionGTKTimeCB mTimeCB;
|
||||
};
|
||||
|
||||
#endif // nsDragService_h__
|
||||
|
|
|
@ -852,6 +852,10 @@ handle_gdk_event (GdkEvent *event, gpointer data)
|
|||
{
|
||||
GtkObject *object = nsnull;
|
||||
|
||||
guint32 event_time = gdk_event_get_time(event);
|
||||
if (event_time)
|
||||
nsWidget::SetLastEventTime(event_time);
|
||||
|
||||
if (event->any.window)
|
||||
gdk_window_get_user_data (event->any.window, (void **)&object);
|
||||
|
||||
|
|
|
@ -76,6 +76,9 @@ PRUint32 nsWidget::sWidgetCount = 0;
|
|||
// this is the nsWindow with the focus
|
||||
nsWidget *nsWidget::focusWindow = NULL;
|
||||
|
||||
// this is the last time that an event happened. we keep this
|
||||
// around so that we can synth drag events properly
|
||||
guint32 nsWidget::sLastEventTime = 0;
|
||||
|
||||
PRBool nsWidget::OnInput(nsInputEvent &aEvent)
|
||||
{
|
||||
|
@ -101,6 +104,18 @@ PRBool nsWidget::OnInput(nsInputEvent &aEvent)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void nsWidget::SetLastEventTime(guint32 aTime)
|
||||
{
|
||||
sLastEventTime = aTime;
|
||||
}
|
||||
|
||||
void nsWidget::GetLastEventTime(guint32 *aTime)
|
||||
{
|
||||
if (aTime)
|
||||
*aTime = sLastEventTime;
|
||||
}
|
||||
|
||||
nsresult nsWidget::KillICSpotTimer ()
|
||||
{
|
||||
if(mICSpotTimer)
|
||||
|
@ -169,6 +184,7 @@ nsCOMPtr<nsIRollupListener> nsWidget::gRollupListener;
|
|||
nsCOMPtr<nsIWidget> nsWidget::gRollupWidget;
|
||||
PRBool nsWidget::gRollupConsumeRollupEvent = PR_FALSE;
|
||||
PRBool nsWidget::mGDKHandlerInstalled = PR_FALSE;
|
||||
PRBool nsWidget::mTimeCBSet = PR_FALSE;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
// debugging window
|
||||
|
@ -263,6 +279,24 @@ nsWidget::nsWidget()
|
|||
// they have been converted to GDK, but before GTK+ gets them
|
||||
gdk_event_handler_set (handle_gdk_event, NULL, NULL);
|
||||
}
|
||||
if (mTimeCBSet == PR_FALSE) {
|
||||
mTimeCBSet = PR_TRUE;
|
||||
nsCOMPtr<nsIDragService> dragService;
|
||||
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
|
||||
nsIDragService::GetIID(),
|
||||
(nsISupports **)&dragService);
|
||||
if (NS_FAILED(rv)) {
|
||||
g_print("*** warning: failed to get the drag service. this is a _bad_ thing.\n");
|
||||
mTimeCBSet = PR_FALSE;
|
||||
}
|
||||
nsCOMPtr<nsIDragSessionGTK> dragServiceGTK;
|
||||
dragServiceGTK = do_QueryInterface(dragService);
|
||||
if (!dragServiceGTK) {
|
||||
mTimeCBSet = PR_FALSE;
|
||||
return;
|
||||
}
|
||||
dragServiceGTK->SetTimeCallback(nsWidget::GetLastEventTime);
|
||||
}
|
||||
#ifdef NS_DEBUG
|
||||
// see if we need to set up the debugging window
|
||||
if (!debugCheckedDebugWindow) {
|
||||
|
@ -3150,6 +3184,25 @@ void nsWidget::UpdateDragContext(GtkWidget *aWidget, GdkDragContext *aGdkDragCon
|
|||
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
void nsWidget::UpdateDragStatus(GtkWidget *aWidget, GdkDragContext *aGdkDragContext, guint aTime)
|
||||
{
|
||||
// make sure that we tell the drag manager what the hell is going on.
|
||||
nsCOMPtr<nsIDragService> dragService;
|
||||
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
|
||||
nsIDragService::GetIID(),
|
||||
(nsISupports **)&dragService);
|
||||
if (NS_FAILED(rv)) {
|
||||
g_print("*** warning: failed to get the drag service. this is a _bad_ thing.\n");
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIDragSessionGTK> dragServiceGTK;
|
||||
dragServiceGTK = do_QueryInterface(dragService);
|
||||
if (!dragServiceGTK) {
|
||||
return;
|
||||
}
|
||||
dragServiceGTK->UpdateDragStatus(aWidget, aGdkDragContext, aTime);
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
|
||||
|
|
|
@ -191,9 +191,14 @@ public:
|
|||
PRBool OnText(nsTextEvent &aEvent) { return OnInput(aEvent); };
|
||||
PRBool OnComposition(nsCompositionEvent &aEvent) { return OnInput(aEvent); };
|
||||
PRBool OnInput(nsInputEvent &aEvent);
|
||||
|
||||
// the event handling code needs to let us know the time of the last event
|
||||
static void SetLastEventTime(guint32 aTime);
|
||||
static void GetLastEventTime(guint32 *aTime);
|
||||
protected:
|
||||
|
||||
virtual void UpdateDragContext(GtkWidget *aWidget, GdkDragContext *aGdkDragContext, guint aTime);
|
||||
virtual void UpdateDragStatus(GtkWidget *aWidget, GdkDragContext *aGdkDragContext, guint aTime);
|
||||
|
||||
virtual void InitCallbacks(char * aName = nsnull);
|
||||
|
||||
|
@ -453,6 +458,9 @@ protected:
|
|||
|
||||
nsITimer* mICSpotTimer;
|
||||
static void ICSpotCallback(nsITimer* aTimer, void* aClosure);
|
||||
// this is the last time that an event happened. we keep this
|
||||
// around so that we can synth drag events properly
|
||||
static guint32 sLastEventTime;
|
||||
public:
|
||||
nsresult KillICSpotTimer();
|
||||
nsresult PrimeICSpotTimer();
|
||||
|
@ -467,6 +475,9 @@ private:
|
|||
// this will keep track of whether or not the gdk handler
|
||||
// is installed yet
|
||||
static PRBool mGDKHandlerInstalled;
|
||||
// this will keep track of whether or not we've told the drag
|
||||
// service how to call back into us to get the last event time
|
||||
static PRBool mTimeCBSet;
|
||||
|
||||
//
|
||||
// Keep track of the last widget being "dragged"
|
||||
|
|
|
@ -1158,74 +1158,6 @@ nsWindow::HandleGDKEvent(GdkEvent *event)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// this code does it the ugly way.
|
||||
XEvent xevent;
|
||||
|
||||
switch (event->any.type)
|
||||
{
|
||||
case GDK_MOTION_NOTIFY:
|
||||
OnMotionNotifySignal (&event->motion);
|
||||
break;
|
||||
case GDK_BUTTON_PRESS:
|
||||
case GDK_2BUTTON_PRESS:
|
||||
case GDK_3BUTTON_PRESS:
|
||||
{
|
||||
GdkEventMask mask = (GdkEventMask)(GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_FOCUS_CHANGE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK);
|
||||
|
||||
gdk_window_set_events(((GdkEventButton*)event)->window,
|
||||
mask);
|
||||
OnButtonPressSignal (&event->button);
|
||||
|
||||
|
||||
while (!XCheckTypedEvent(GDK_DISPLAY(), ButtonRelease, &xevent)) {
|
||||
int x,y;
|
||||
gdk_window_get_pointer(((GdkEventButton*)event)->window, &x, &y, nsnull);
|
||||
XMotionEvent bevent;
|
||||
bevent.x = x;
|
||||
bevent.y = y;
|
||||
HandleXlibMotionNotifyEvent(&bevent);
|
||||
}
|
||||
XPutBackEvent(GDK_DISPLAY(), &xevent);
|
||||
|
||||
printf("button press finished\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case GDK_BUTTON_RELEASE:
|
||||
{
|
||||
GdkEventMask mask = (GdkEventMask)(GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
GDK_LEAVE_NOTIFY_MASK |
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_FOCUS_CHANGE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
|
||||
gdk_window_set_events(((GdkEventButton*)event)->window,
|
||||
mask);
|
||||
|
||||
HandleXlibButtonEvent((XButtonEvent *)event);
|
||||
}
|
||||
|
||||
OnButtonReleaseSignal (&event->button);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1499,10 +1431,8 @@ nsWindow::OnToplevelDragMotion (GtkWidget *aWidget,
|
|||
|
||||
innerMostWidget->Release();
|
||||
|
||||
// make sure that we set our drag context
|
||||
GdkDragAction action = GDK_ACTION_COPY;
|
||||
gdk_drag_status(aDragContext, action, aTime);
|
||||
|
||||
// now that we've dispatched the signal, update the drag context
|
||||
UpdateDragStatus(aWidget, aDragContext, aTime);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Загрузка…
Ссылка в новой задаче