first pass at DND for gtk since superwin. fixes bug #9642. r=pavlov,pinkerton

This commit is contained in:
blizzard%redhat.com 2000-02-10 04:19:52 +00:00
Родитель 8cdc9e4a08
Коммит e32f6bfee2
7 изменённых файлов: 785 добавлений и 641 удалений

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

@ -34,12 +34,22 @@ class nsIDragSessionGTK : public nsISupports {
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDRAGSESSIONGTK_IID)
NS_IMETHOD SetLastDragContext(GdkDragContext *aContext) = 0;
NS_IMETHOD SetDragData (GtkWidget *aWidget,
GdkDragContext *aContext,
gint x,
gint y,
guint time) = 0;
NS_IMETHOD SetLastContext (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;
NS_IMETHOD DataGetSignal (GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint32 time,
gpointer data) = 0;
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -1,9 +1,9 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
@ -12,18 +12,19 @@
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
* The Initial Developer of the Original Code is Christopher Blizzard
* <blizzard@mozilla.org>. Portions created by Christopher Blizzard
* are Copyright (C) 1998 Christopher Blizzard. All Rights Reserved.
*
* Contributor(s):
*/
* Contributor(s):
* Christopher Blizzard <blizzard@mozilla.org>
*/
#ifndef nsDragService_h__
#define nsDragService_h__
#include "nsBaseDragService.h"
#include "nsIDragSessionGTK.h"
#include <gtk/gtk.h>
@ -31,7 +32,7 @@
* Native GTK DragService wrapper
*/
class nsDragService : public nsBaseDragService
class nsDragService : public nsBaseDragService, public nsIDragSessionGTK
{
public:
@ -42,78 +43,66 @@ public:
// nsIDragService
NS_IMETHOD InvokeDragSession (nsISupportsArray * anArrayTransferables,
nsIScriptableRegion * aRegion, PRUint32 aActionType);
NS_IMETHOD GetCurrentSession (nsIDragSession ** aSession);
// nsIDragSession
NS_IMETHOD GetData (nsITransferable * aTransferable, PRUint32 anItem);
NS_IMETHOD GetNumDropItems (PRUint32 * aNumItems);
NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval);
nsIScriptableRegion * aRegion,
PRUint32 aActionType);
NS_IMETHOD StartDragSession();
NS_IMETHOD EndDragSession();
GtkTargetList *RegisterDragItemsAndFlavors(nsISupportsArray *inArray);
// nsIDragSession
NS_IMETHOD SetCanDrop (PRBool aCanDrop);
NS_IMETHOD GetCanDrop (PRBool *aCanDrop);
NS_IMETHOD GetNumDropItems (PRUint32 * aNumItems);
NS_IMETHOD GetData (nsITransferable * aTransferable, PRUint32 anItemIndex);
NS_IMETHOD IsDataFlavorSupported (const char *aDataFlavor, PRBool *_retval);
protected:
// nsIDragSessionGTK
NS_IMETHOD SetLastContext (GtkWidget *aWidget,
GdkDragContext *aContext,
guint aTime);
NS_IMETHOD SetDataReceived (GtkWidget *aWidget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint32 time);
NS_IMETHOD DataGetSignal (GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint32 time,
gpointer data);
static void SelectionReceivedCB (GtkWidget *aWidget,
GdkDragContext *aContext,
gint aX,
gint aY,
GtkSelectionData *aSelectionData,
guint aInfo,
guint aTime);
void SelectionReceiver (GtkWidget *aWidget, GtkSelectionData *aSD);
PRBool DoConvert(GdkAtom type);
static PRBool gHaveDrag;
static void DragLeave(GtkWidget *widget,
GdkDragContext *context,
guint time);
static PRBool DragMotion(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static PRBool DragDrop(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static void DragDataReceived(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *data,
guint info,
guint time);
static void DragDataGet(GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data);
static void DragDataDelete(GtkWidget *widget,
GdkDragContext *context,
gpointer data);
// END PUBLIC API
private:
GdkDragAction mActionType;
PRUint32 mNumFlavors;
GtkWidget *mWidget;
GdkDragContext *mDragContext;
GtkSelectionData mSelectionData;
PRBool mBlocking;
// this is the hidden widget where we get our data
// we start drags from and where we do a grab when we
// are waiting for our DND data back
GtkWidget *mHiddenWidget;
// here's the last drag context
GdkDragContext *mLastContext;
// this is the last widget that had a drag event
GtkWidget *mLastWidget;
// the last time a drag event happened.
guint mLastTime;
// this is the list of data items that we support when we've
// started a drag
nsISupportsArray *mDataItems;
// have we gotten our drag data yet?
PRBool mDataReceived;
// this is where the actual drag data is received
void *mDragData;
PRUint32 mDragDataLen;
// this will reset all of our drag state
void ResetDragState(void);
// set our local data items list and addref it properly
void SetDataItems(nsISupportsArray *anArray);
// get the data for a particular flavor
NS_METHOD GetNativeDragData(GdkAtom aFlavor);
};
#endif // nsDragService_h__

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

@ -35,6 +35,8 @@
#include <gdk/gdkx.h>
#include "nsIRollupListener.h"
#include "nsIServiceManager.h"
#include "nsIDragSessionGTK.h"
#include "nsIDragService.h"
#include "nsGtkUtils.h" // for nsGtkUtils::gdk_keyboard_get_modifiers()
@ -47,6 +49,7 @@
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
static NS_DEFINE_IID(kCDragServiceCID, NS_DRAGSERVICE_CID);
// keeping track of a list of simultaneously modal widgets
class ModalWidgetList {
@ -198,21 +201,6 @@ gint nsWidget::sButtonMotionRootY = -1;
gint nsWidget::sButtonMotionWidgetX = -1;
gint nsWidget::sButtonMotionWidgetY = -1;
// Drag & Drop stuff.
enum {
TARGET_STRING,
TARGET_ROOTWIN
};
static GtkTargetEntry target_table[] = {
{ "STRING", 0, TARGET_STRING },
{ "text/plain", 0, TARGET_STRING },
{ "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
};
static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
//#undef DEBUG_pavlov
nsWidget::nsWidget()
@ -1126,16 +1114,17 @@ nsresult nsWidget::CreateWidget(nsIWidget *aParent,
// Initialize this window instance as a drag target.
gtk_drag_dest_set (mWidget,
GTK_DEST_DEFAULT_ALL,
target_table, n_targets - 1, /* no rootwin */
GdkDragAction(GDK_ACTION_COPY | GDK_ACTION_MOVE));
(GtkDestDefaults)0,
NULL,
0,
(GdkDragAction)0);
// Drag & Drop events.
InstallDragBeginSignal(mWidget);
InstallDragLeaveSignal(mWidget);
InstallDragMotionSignal(mWidget);
InstallDragDropSignal(mWidget);
InstallDragDataReceived(mWidget);
// Focus
InstallFocusInSignal(mWidget);
@ -1508,6 +1497,16 @@ nsWidget::InstallDragDropSignal(GtkWidget * aWidget)
GTK_SIGNAL_FUNC(nsWidget::DragDropSignal));
}
void
nsWidget::InstallDragDataReceived(GtkWidget *aWidget)
{
NS_ASSERTION( nsnull != aWidget, "widget is null");
InstallSignal(aWidget,
(gchar *)"drag_data_received",
GTK_SIGNAL_FUNC(nsWidget::DragDataReceivedSignal));
}
//////////////////////////////////////////////////////////////////
void
nsWidget::InstallEnterNotifySignal(GtkWidget * aWidget)
@ -1714,6 +1713,10 @@ nsWidget::OnDragEnterSignal(GdkDragContext *aGdkDragContext,
gint y,
guint aTime)
{
// make sure that we tell the drag manager what the hell is going on.
UpdateDragContext(NULL, aGdkDragContext, aTime);
// we are a drag dest.. cool huh?
mIsDragDest = PR_TRUE;
@ -1738,8 +1741,10 @@ nsWidget::OnDragEnterSignal(GdkDragContext *aGdkDragContext,
nsWidget::OnDragLeaveSignal(GdkDragContext *context,
guint aTime)
{
mIsDragDest = PR_FALSE;
// update our drag context
UpdateDragContext(NULL, NULL, aTime);
mIsDragDest = PR_FALSE;
nsMouseEvent event;
@ -1781,11 +1786,14 @@ nsWidget::OnDragBeginSignal(GdkDragContext * aGdkDragContext)
/* virtual */ void
nsWidget::OnDragDropSignal(GdkDragContext *aDragContext,
nsWidget::OnDragDropSignal(GtkWidget *aWidget,
GdkDragContext *aDragContext,
gint x,
gint y,
guint aTime)
{
UpdateDragContext(aWidget, aDragContext, aTime);
nsMouseEvent event;
event.message = NS_DRAGDROP_DROP;
@ -1800,8 +1808,43 @@ nsWidget::OnDragDropSignal(GdkDragContext *aDragContext,
DispatchWindowEvent(&event);
Release();
// 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.
UpdateDragContext(NULL, NULL, 0);
}
/* virtual */
void nsWidget::OnDragDataReceivedSignal(GtkWidget *aWidget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint32 aTime)
{
// the service is the only one that cares that we get this.
g_print("nsWidget::OnDragDataReceivedSignal\n");
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->SetDataReceived(aWidget, context, x, y, selection_data, info, aTime);
}
//////////////////////////////////////////////////////////////////
/* virtual */ void
@ -2380,12 +2423,30 @@ nsWidget::DragDropSignal(GtkWidget * aWidget,
}
#endif
widget->OnDragDropSignal(aDragContext, x, y, aTime);
widget->OnDragDropSignal(aWidget, aDragContext, x, y, aTime);
return PR_TRUE;
}
/* static */
void
nsWidget::DragDataReceivedSignal(GtkWidget *aWidget,
GdkDragContext *aDragContext,
gint x,
gint y,
GtkSelectionData *aSelectionData,
guint aInfo,
guint32 aTime,
gpointer aData)
{
NS_ASSERTION(nsnull != aWidget, "widget is null");
NS_ASSERTION(nsnull != aDragContext, "dragcontext is null");
nsWidget *widget = (nsWidget *)aData;
NS_ASSERTION( nsnull != widget, "instance pointer is null");
widget->OnDragDataReceivedSignal(aWidget, aDragContext, x, y, aSelectionData, aInfo, aTime);
}
//////////////////////////////////////////////////////////////////
@ -3061,6 +3122,29 @@ GtkWindow *nsWidget::GetTopLevelWindow(void)
return NULL;
}
/* virtual */
void nsWidget::UpdateDragContext(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->SetLastContext(aWidget, aGdkDragContext, aTime);
}
#ifdef NS_DEBUG
static void setDebugWindow(void)

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

@ -192,6 +192,8 @@ public:
PRBool OnInput(nsInputEvent &aEvent);
protected:
virtual void UpdateDragContext(GtkWidget *aWidget, GdkDragContext *aGdkDragContext, guint aTime);
virtual void InitCallbacks(char * aName = nsnull);
NS_IMETHOD CreateNative(GtkObject *parentWindow) { return NS_OK; }
@ -241,6 +243,7 @@ protected:
void InstallDragLeaveSignal(GtkWidget * aWidget);
void InstallDragBeginSignal(GtkWidget * aWidget);
void InstallDragDropSignal(GtkWidget * aWidget);
void InstallDragDataReceived(GtkWidget * aWidget);
void InstallEnterNotifySignal(GtkWidget * aWidget);
@ -279,10 +282,18 @@ protected:
virtual void OnDragLeaveSignal(GdkDragContext *context,
guint time);
virtual void OnDragBeginSignal(GdkDragContext *aGdkDragContext);
virtual void OnDragDropSignal(GdkDragContext *aGdkDragContext,
virtual void OnDragDropSignal(GtkWidget *aWidget,
GdkDragContext *aGdkDragContext,
gint x,
gint y,
guint time);
virtual void OnDragDataReceivedSignal(GtkWidget *aWidget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint32 time);
virtual void OnEnterNotifySignal(GdkEventCrossing * aGdkCrossingEvent);
virtual void OnLeaveNotifySignal(GdkEventCrossing * aGdkCrossingEvent);
virtual void OnButtonPressSignal(GdkEventButton * aGdkButtonEvent);
@ -345,7 +356,14 @@ protected:
guint time,
void *data);
static void DragDataReceivedSignal(GtkWidget *aWidget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint32 time,
gpointer data);
static gint EnterNotifySignal(GtkWidget * aWidget,
GdkEventCrossing * aGdkCrossingEvent,

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

@ -93,21 +93,6 @@ static void printDepth(int depth) {
}
}
// Drag & Drop stuff.
enum {
TARGET_STRING,
TARGET_ROOTWIN
};
static GtkTargetEntry target_table[] = {
{ "STRING", 0, TARGET_STRING },
{ "text/plain", 0, TARGET_STRING },
{ "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
};
static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsWidget)
//-------------------------------------------------------------------------
@ -1100,8 +1085,34 @@ nsWindow::HandleGDKEvent(GdkEvent *event)
case GDK_MOTION_NOTIFY:
{
XEvent xevent;
while (XCheckMaskEvent(GDK_DISPLAY(), ButtonMotionMask, &xevent));
OnMotionNotifySignal (&event->motion);
GdkEvent gdk_event;
PRBool synthEvent = PR_FALSE;
while (XCheckWindowEvent(GDK_DISPLAY(),
GDK_WINDOW_XWINDOW(mSuperWin->bin_window),
ButtonMotionMask, &xevent)) {
synthEvent = PR_TRUE;
}
if (synthEvent) {
gdk_event.type = GDK_MOTION_NOTIFY;
gdk_event.motion.window = event->motion.window;
gdk_event.motion.send_event = event->motion.send_event;
gdk_event.motion.time = xevent.xmotion.time;
gdk_event.motion.x = xevent.xmotion.x;
gdk_event.motion.y = xevent.xmotion.y;
gdk_event.motion.pressure = event->motion.pressure;
gdk_event.motion.xtilt = event->motion.xtilt;
gdk_event.motion.ytilt = event->motion.ytilt;
gdk_event.motion.state = event->motion.state;
gdk_event.motion.is_hint = xevent.xmotion.is_hint;
gdk_event.motion.source = event->motion.source;
gdk_event.motion.deviceid = event->motion.deviceid;
gdk_event.motion.x_root = xevent.xmotion.x_root;
gdk_event.motion.y_root = xevent.xmotion.y_root;
OnMotionNotifySignal (&gdk_event.motion);
}
else {
OnMotionNotifySignal (&event->motion);
}
}
break;
case GDK_BUTTON_PRESS:
@ -1184,9 +1195,33 @@ nsWindow::HandleGDKEvent(GdkEvent *event)
}
#endif
}
void
nsWindow::InstallToplevelDragDataReceivedSignal(void)
{
NS_ASSERTION( nsnull != mShell, "mShell is null");
InstallSignal(mShell,
(gchar *)"drag_data_received",
GTK_SIGNAL_FUNC(nsWindow::ToplevelDragDataReceivedSignal));
}
/* static */
void nsWindow::ToplevelDragDataReceivedSignal(GtkWidget *aWidget,
GdkDragContext *aDragContext,
gint x,
gint y,
GtkSelectionData *aSelectionData,
guint aInfo,
guint32 aTime,
gpointer aData)
{
nsWindow *widget = (nsWindow *)aData;
NS_ASSERTION(nsnull != widget, "instance pointer is null");
widget->OnDragDataReceivedSignal(aWidget, aDragContext, x, y, aSelectionData, aInfo, aTime);
}
void
nsWindow::InstallToplevelDragBeginSignal(void)
@ -1228,7 +1263,6 @@ nsWindow::ToplevelDragLeaveSignal(GtkWidget * aWidget,
guint aTime,
void *aData)
{
g_print("nsWindow::ToplevelDragLeaveSignal\n");
if (mLastDragMotionWindow) {
mLastDragMotionWindow->OnDragLeaveSignal(aDragContext, aTime);
mLastLeaveWindow = mLastDragMotionWindow;
@ -1267,7 +1301,7 @@ nsWindow::ToplevelDragMotionSignal(GtkWidget * aWidget,
widget->OnToplevelDragMotion(aWidget, aDragContext, x, y, time);
return PR_TRUE;
return TRUE;
}
#ifdef NS_DEBUG
@ -1434,6 +1468,10 @@ 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);
}
void
@ -1455,9 +1493,8 @@ nsWindow::ToplevelDragDropSignal(GtkWidget * aWidget,
guint aTime,
void *aData)
{
g_print("nsWindow::ToplevelDragDropSignal\n");
if (mLastLeaveWindow) {
mLastLeaveWindow->OnDragDropSignal(aDragContext, x, y, aTime);
mLastLeaveWindow->OnDragDropSignal(aWidget, aDragContext, x, y, aTime);
mLastLeaveWindow = NULL;
}
return PR_FALSE;
@ -1686,11 +1723,13 @@ NS_METHOD nsWindow::CreateNative(GtkObject *parentWidget)
InstallToplevelDragLeaveSignal();
InstallToplevelDragMotionSignal();
InstallToplevelDragDropSignal();
InstallToplevelDragDataReceivedSignal();
// set the shell window as a drop target
gtk_drag_dest_set (mShell,
GTK_DEST_DEFAULT_ALL,
target_table, n_targets - 1, /* no rootwin */
GdkDragAction(GDK_ACTION_COPY | GDK_ACTION_MOVE));
(GtkDestDefaults)0,
NULL,
0,
(GdkDragAction)0);
}
if (mSuperWin) {

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

@ -105,6 +105,7 @@ public:
void InstallToplevelDragLeaveSignal (void);
void InstallToplevelDragMotionSignal(void);
void InstallToplevelDragDropSignal (void);
void InstallToplevelDragDataReceivedSignal(void);
static gint ToplevelDragBeginSignal (GtkWidget * aWidget,
GdkDragContext *aDragContext,
@ -129,6 +130,15 @@ public:
guint aTime,
void *aData);
static void ToplevelDragDataReceivedSignal(GtkWidget *aWidget,
GdkDragContext *aDragContext,
gint x,
gint y,
GtkSelectionData *aSelectionData,
guint aInfo,
guint32 aTime,
gpointer aData);
void OnToplevelDragMotion (GtkWidget *aWidget,
GdkDragContext *aGdkDragContext,
gint x,