# HG changeset patch
# User Dan Pascu <[EMAIL PROTECTED]>
# Date 1137961999 28800
# Branch wm_0_92
# Node ID cc87d65fc6e2fbb90fca58062516dc3102911f01
# Parent 5bef22c8d8ee9e8c47f980fe792d82aa3284b0d7
- updated the XDND code in WINGs to work with GDK based applications.
WINGs based applications should now work with both KDE and GNOME
applications (Sylvain Reynal <[EMAIL PROTECTED]>)
- better check for the XDND protocol version when interoperating with other
applications. As it seems xdnd version 3 (which WINGs supports) and newer
are not backward compatible with xdnd version 1 and 2. This is why WINGs
applications cannot interoperate with GNUstep applications (which uses
xdnd version 2). Xdnd version 4 and 5 are backwards compatible with
version 3 though. (Sylvain Reynal <[EMAIL PROTECTED]>)
(transplanted from 8f56a7f1f034f721550857b17c1bfe1b3d91104a)
diff -r 5bef22c8d8ee -r cc87d65fc6e2 ChangeLog
--- a/ChangeLog Sun Jan 22 11:20:57 2006 -0800
+++ b/ChangeLog Sun Jan 22 12:33:19 2006 -0800
@@ -21,6 +21,15 @@
- fixed a small memory leak in WINGs/wview.c caused by not releasing the
background color of a view (Martin Frydl <[EMAIL PROTECTED]>)
- updated estonian translation (Ivar Smolin <[EMAIL PROTECTED]>)
+- updated the XDND code in WINGs to work with GDK based applications.
+ WINGs based applications should now work with both KDE and GNOME
+ applications (Sylvain Reynal <[EMAIL PROTECTED]>)
+- better check for the XDND protocol version when interoperating with other
+ applications. As it seems xdnd version 3 (which WINGs supports) and newer
+ are not backward compatible with xdnd version 1 and 2. This is why WINGs
+ applications cannot interoperate with GNUstep applications (which uses
+ xdnd version 2). Xdnd version 4 and 5 are backwards compatible with
+ version 3 though. (Sylvain Reynal <[EMAIL PROTECTED]>)
Changes since version 0.91.0:
diff -r 5bef22c8d8ee -r cc87d65fc6e2 WINGs/ChangeLog
--- a/WINGs/ChangeLog Sun Jan 22 11:20:57 2006 -0800
+++ b/WINGs/ChangeLog Sun Jan 22 12:33:19 2006 -0800
@@ -1,3 +1,17 @@
+Changes since wmaker 0.92.0:
+............................
+
+- updated the XDND code in to work with GDK based applications.
+ WINGs based applications should now work with both KDE and GNOME
+ applications (Sylvain Reynal <[EMAIL PROTECTED]>)
+- better check for the XDND protocol version when interoperating with other
+ applications. As it seems xdnd version 3 (which WINGs supports) and newer
+ are not backward compatible with xdnd version 1 and 2. This is why WINGs
+ applications cannot interoperate with GNUstep applications (which uses
+ xdnd version 2). Xdnd version 4 and 5 are backwards compatible with
+ version 3 though. (Sylvain Reynal <[EMAIL PROTECTED]>)
+
+
Changes since wmaker 0.80.1:
............................
diff -r 5bef22c8d8ee -r cc87d65fc6e2 WINGs/WINGs/WINGsP.h
--- a/WINGs/WINGs/WINGsP.h Sun Jan 22 11:20:57 2006 -0800
+++ b/WINGs/WINGs/WINGsP.h Sun Jan 22 12:33:19 2006 -0800
@@ -29,7 +29,7 @@
#define SCROLLER_WIDTH 20
-#define XDND_VERSION 4
+#define XDND_VERSION 3
typedef struct W_Application {
@@ -78,7 +78,7 @@
typedef struct W_FocusInfo {
struct W_View *toplevel;
- struct W_View *focused; /* view that has the focus in this
toplevel */
+ struct W_View *focused; /* view that has the focus in this toplevel */
struct W_FocusInfo *next;
} W_FocusInfo;
@@ -110,8 +110,10 @@
typedef struct W_DragDestinationInfo {
WMView *destView;
+ WMView *xdndAwareView;
Window sourceWindow;
W_DndState *state;
+ Bool sourceActionChanged;
WMArray *sourceTypes;
WMArray *requiredTypes;
Bool typeListAvailable;
@@ -120,7 +122,7 @@
struct W_DraggingInfo {
- unsigned char protocolVersion;
+ unsigned char protocolVersion; /* version supported on the other side */
Time timestamp;
Atom sourceAction;
@@ -162,7 +164,7 @@
struct W_Window *windowList; /* list of windows in the app */
- Window groupLeader; /* the leader of the application
*/
+ Window groupLeader; /* the leader of the application */
/* also used for other things */
struct W_SelectionHandlers *selectionHandlerList;
@@ -195,11 +197,11 @@
GC copyGC;
GC clipGC;
- GC monoGC; /* GC for 1bpp visuals */
+ GC monoGC; /* GC for 1bpp visuals */
GC xorGC;
- GC ixorGC; /* IncludeInferiors XOR */
+ GC ixorGC; /* IncludeInferiors XOR */
GC drawStringGC; /* for WMDrawString() */
@@ -276,15 +278,15 @@
Cursor invisibleCursor;
- Atom attribsAtom; /* GNUstepWindowAttributes */
+ Atom attribsAtom; /* GNUstepWindowAttributes */
- Atom deleteWindowAtom; /* WM_DELETE_WINDOW */
+ Atom deleteWindowAtom; /* WM_DELETE_WINDOW */
- Atom protocolsAtom; /* _XA_WM_PROTOCOLS */
+ Atom protocolsAtom; /* _XA_WM_PROTOCOLS */
- Atom clipboardAtom; /* CLIPBOARD */
+ Atom clipboardAtom; /* CLIPBOARD */
- Atom xdndAwareAtom; /* XdndAware */
+ Atom xdndAwareAtom; /* XdndAware */
Atom xdndSelectionAtom;
Atom xdndEnterAtom;
Atom xdndLeaveAtom;
@@ -304,7 +306,7 @@
Atom wmIconDragOffsetAtom;
- Atom wmStateAtom; /* WM_STATE */
+ Atom wmStateAtom; /* WM_STATE */
Atom utf8String;
@@ -313,8 +315,8 @@
Atom netwmIcon;
/* stuff for detecting double-clicks */
- Time lastClickTime; /* time of last mousedown event
*/
- Window lastClickWindow; /* window of the last mousedown */
+ Time lastClickTime; /* time of last mousedown event */
+ Window lastClickWindow; /* window of the last mousedown */
struct W_View *modalView;
unsigned modalLoop:1;
@@ -341,8 +343,7 @@
typedef struct W_View {
struct W_Screen *screen;
- WMWidget *self; /* must point to the widget the
- * view belongs to */
+ WMWidget *self; /* must point to the widget the view belongs to */
W_ViewDelegate *delegate;
@@ -362,18 +363,18 @@
struct W_View *nextResponder; /* next to receive keyboard events */
- struct W_View *parent; /* parent WMView */
+ struct W_View *parent; /* parent WMView */
struct W_View *childrenList; /* first in list of child windows */
- struct W_View *nextSister; /* next on parent's children list */
+ struct W_View *nextSister; /* next on parent's children list */
- WMArray *eventHandlers; /* event handlers for this window */
+ WMArray *eventHandlers; /* event handlers for this window */
unsigned long attribFlags;
XSetWindowAttributes attribs;
- void *hangedData; /* data holder for user program */
+ void *hangedData; /* data holder for user program */
WMColor *backColor;
@@ -391,9 +392,9 @@
unsigned int realized:1;
unsigned int mapped:1;
unsigned int parentDying:1;
- unsigned int dying:1; /* the view is being destroyed */
+ unsigned int dying:1; /* the view is being destroyed */
unsigned int topLevel:1; /* is a top level window */
- unsigned int root:1; /* is the root window */
+ unsigned int root:1; /* is the root window */
unsigned int mapWhenRealized:1; /* map the view when it's realized */
unsigned int alreadyDead:1; /* view was freed */
diff -r 5bef22c8d8ee -r cc87d65fc6e2 WINGs/dragcommon.c
--- a/WINGs/dragcommon.c Sun Jan 22 11:20:57 2006 -0800
+++ b/WINGs/dragcommon.c Sun Jan 22 12:33:19 2006 -0800
@@ -2,11 +2,9 @@
#include "WINGsP.h"
-#define VERSION_INFO(dragInfo) dragInfo->protocolVersion
+#define XDND_SOURCE_VERSION(dragInfo) dragInfo->protocolVersion
#define XDND_DEST_INFO(dragInfo) dragInfo->destInfo
#define XDND_DEST_VIEW(dragInfo) dragInfo->destInfo->destView
-#define XDND_DEST_VIEW_STORED(dragInfo) ((dragInfo->destInfo) != NULL)\
- && ((dragInfo->destInfo->destView) != NULL)
static Bool _WindowExists;
@@ -151,6 +149,13 @@
{
XEvent ev;
+#ifdef XDND_DEBUG
+ char* msgName = XGetAtomName(dpy, message);
+
+ printf("sending message %s ... ", msgName);
+ XFree(msgName);
+#endif
+
if (! windowExists(dpy, win)) {
wwarning("xdnd message target %d does no longer exist.", win);
return False; /* message not sent */
@@ -170,6 +175,9 @@
XSendEvent(dpy, win, False, 0, &ev);
XFlush(dpy);
+#ifdef XDND_DEBUG
+ printf("sent\n");
+#endif
return True; /* message sent */
}
@@ -178,7 +186,9 @@
handleLeaveMessage(WMDraggingInfo *info)
{
if (XDND_DEST_INFO(info) != NULL) {
- if (XDND_DEST_VIEW(info) != NULL) {
+ /* XDND_DEST_VIEW is never NULL (it's the xdnd aware view) */
+ wassertr(XDND_DEST_VIEW(info) != NULL);
+ if (XDND_DEST_VIEW(info)->dragDestinationProcs != NULL) {
XDND_DEST_VIEW(info)->dragDestinationProcs->concludeDragOperation(
XDND_DEST_VIEW(info));
}
@@ -216,11 +226,15 @@
/* Messages from source to destination */
if (messageType == scr->xdndEnterAtom) {
+ Bool positionSent = (XDND_DEST_INFO(info) != NULL);
+
W_DragDestinationStopTimer();
W_DragDestinationStoreEnterMsgInfo(info, toplevel, event);
- if (VERSION_INFO(info) <= XDND_VERSION) {
- if (XDND_DEST_VIEW_STORED(info)) {
+ /* Xdnd version 3 and up are not compatible with version 1 or 2 */
+ if (XDND_SOURCE_VERSION(info) > 2) {
+
+ if (positionSent) {
/* xdndPosition previously received on xdnd aware view */
W_DragDestinationStateHandler(info, event);
return;
@@ -230,7 +244,7 @@
}
} else {
wwarning("received dnd enter msg with unsupported version %i",
- VERSION_INFO(info));
+ XDND_SOURCE_VERSION(info));
W_DragDestinationCancelDropOnEnter(toplevel, info);
return;
}
diff -r 5bef22c8d8ee -r cc87d65fc6e2 WINGs/dragdestination.c
--- a/WINGs/dragdestination.c Sun Jan 22 11:20:57 2006 -0800
+++ b/WINGs/dragdestination.c Sun Jan 22 12:33:19 2006 -0800
@@ -5,15 +5,16 @@
#define XDND_SOURCE_RESPONSE_MAX_DELAY 3000
-#define VERSION_INFO(dragInfo) dragInfo->protocolVersion
-
#define XDND_PROPERTY_FORMAT 32
#define XDND_ACTION_DESCRIPTION_FORMAT 8
+#define XDND_SOURCE_VERSION(dragInfo) dragInfo->protocolVersion
#define XDND_DEST_INFO(dragInfo) dragInfo->destInfo
+#define XDND_AWARE_VIEW(dragInfo) dragInfo->destInfo->xdndAwareView
#define XDND_SOURCE_WIN(dragInfo) dragInfo->destInfo->sourceWindow
#define XDND_DEST_VIEW(dragInfo) dragInfo->destInfo->destView
#define XDND_DEST_STATE(dragInfo) dragInfo->destInfo->state
+#define XDND_SOURCE_ACTION_CHANGED(dragInfo)
dragInfo->destInfo->sourceActionChanged
#define XDND_SOURCE_TYPES(dragInfo) dragInfo->destInfo->sourceTypes
#define XDND_TYPE_LIST_AVAILABLE(dragInfo)
dragInfo->destInfo->typeListAvailable
#define XDND_REQUIRED_TYPES(dragInfo) dragInfo->destInfo->requiredTypes
@@ -22,8 +23,8 @@
#define XDND_SOURCE_OPERATIONS(dragInfo) dragInfo->destInfo->sourceOperations
#define XDND_DROP_DATAS(dragInfo) dragInfo->destInfo->dropDatas
#define XDND_DROP_DATA_COUNT(dragInfo) dragInfo->destInfo->dropDataCount
-#define XDND_DEST_VIEW_STORED(dragInfo) ((dragInfo->destInfo) != NULL)\
- && ((dragInfo->destInfo->destView) != NULL)
+#define XDND_DEST_VIEW_IS_REGISTERED(dragInfo) ((dragInfo->destInfo) != NULL)\
+ && ((dragInfo->destInfo->destView->dragDestinationProcs) != NULL)
static unsigned char XDNDversion = XDND_VERSION;
@@ -81,7 +82,6 @@
static WMArray*
getTypesFromTypeList(WMScreen *scr, Window sourceWin)
{
- /* // WMDraggingInfo *info = &scr->dragInfo;*/
Atom dataType;
Atom* typeAtomList;
WMArray* typeList;
@@ -138,21 +138,28 @@
WMScreen *scr = W_VIEW_SCREEN(destView);
WMArray *requiredTypes;
- /* First, see if the 3 source types are enough for dest requirements */
+ /* First, see if the stored source types are enough for dest requirements
*/
requiredTypes = destView->dragDestinationProcs->requiredDataTypes(
destView,
W_ActionToOperation(scr, XDND_SOURCE_ACTION(info)),
XDND_SOURCE_TYPES(info));
if (requiredTypes == NULL && XDND_TYPE_LIST_AVAILABLE(info)) {
- /* None of the 3 source types fits, get the whole type list */
+ /* None of the stored source types fits, but the whole type list
+ hasn't been retrieved yet. */
+ WMFreeArray(XDND_SOURCE_TYPES(info));
+ XDND_SOURCE_TYPES(info) = getTypesFromTypeList(
+ scr,
+ XDND_SOURCE_WIN(info));
+ /* Don't retrieve the type list again */
+ XDND_TYPE_LIST_AVAILABLE(info) = False;
+
requiredTypes =
destView->dragDestinationProcs->requiredDataTypes(
destView,
W_ActionToOperation(scr, XDND_SOURCE_ACTION(info)),
-
getTypesFromTypeList(scr, XDND_SOURCE_WIN(info)));
+
XDND_SOURCE_TYPES(info));
}
-
XDND_REQUIRED_TYPES(info) = requiredTypes;
}
@@ -249,47 +256,35 @@
}
-static Window
-findChildInWindow(Display *dpy, Window toplevel, int x, int y)
+static WMView*
+findChildInView(WMView* parent, int x, int y)
{
- Window foo, bar;
- Window *children;
- unsigned nchildren;
- int i;
+ if (parent->childrenList == NULL)
+ return parent;
+ else {
+ WMView* child = parent->childrenList;
- if (!XQueryTree(dpy, toplevel, &foo, &bar,
- &children, &nchildren) || children == NULL) {
- return None;
+ while (child != NULL
+ && (! child->flags.mapped
+ || x < WMGetViewPosition(child).x
+ || x > WMGetViewPosition(child).x +
WMGetViewSize(child).width
+ || y < WMGetViewPosition(child).y
+ || y > WMGetViewPosition(child).y +
WMGetViewSize(child).height))
+
+ child = child->nextSister;
+
+ if (child == NULL)
+ return parent;
+ else
+ return findChildInView(child,
+ x - WMGetViewPosition(child).x,
+ y - WMGetViewPosition(child).y);
}
-
- /* first window that contains the point is the one */
- for (i = nchildren-1; i >= 0; i--) {
- XWindowAttributes attr;
-
- if (XGetWindowAttributes(dpy, children[i], &attr)
- && attr.map_state == IsViewable
- && x >= attr.x && y >= attr.y
- && x < attr.x + attr.width && y < attr.y + attr.height) {
- Window child, tmp;
-
- tmp = children[i];
- child = findChildInWindow(dpy, tmp, x - attr.x, y - attr.y);
- XFree(children);
-
- if (child == None)
- return tmp;
- else
- return child;
- }
- }
-
- XFree(children);
- return None;
}
static WMView*
-findXdndViewInToplevel(WMView* toplevel, int x, int y)
+findDestinationViewInToplevel(WMView* toplevel, int x, int y)
{
WMScreen *scr = W_VIEW_SCREEN(toplevel);
Window toplevelWin = WMViewXID(toplevel);
@@ -300,20 +295,7 @@
XTranslateCoordinates(scr->display, scr->rootWin, toplevelWin,
x, y, &xInToplevel, &yInToplevel,
&foo);
-
- child = findChildInWindow(scr->display, toplevelWin,
- xInToplevel, yInToplevel);
-
- if (child != None) {
- childView = W_GetViewForXWindow(scr->display, child);
-
- /* if childView supports Xdnd, return childView */
- if (childView != NULL
- && childView->dragDestinationProcs != NULL)
- return childView;
- }
-
- return NULL;
+ return findChildInView(toplevel, xInToplevel, yInToplevel);
}
@@ -334,6 +316,7 @@
XDND_REQUIRED_TYPES(info) = NULL;
}
+
void
W_DragDestinationInfoClear(WMDraggingInfo *info)
{
@@ -347,15 +330,19 @@
}
}
+
static void
-initDestinationDragInfo(WMDraggingInfo *info)
+initDestinationDragInfo(WMDraggingInfo *info, WMView *destView)
{
+ wassertr(destView != NULL);
+
XDND_DEST_INFO(info) =
(W_DragDestinationInfo*) wmalloc(sizeof(W_DragDestinationInfo));
XDND_DEST_STATE(info) = idleState;
- XDND_DEST_VIEW(info) = NULL;
+ XDND_DEST_VIEW(info) = destView;
+ XDND_SOURCE_ACTION_CHANGED(info) = False;
XDND_SOURCE_TYPES(info) = NULL;
XDND_REQUIRED_TYPES(info) = NULL;
XDND_DROP_DATAS(info) = NULL;
@@ -369,13 +356,19 @@
WMScreen *scr = W_VIEW_SCREEN(toplevel);
if (XDND_DEST_INFO(info) == NULL)
- initDestinationDragInfo(info);
+ initDestinationDragInfo(info, toplevel);
+ XDND_SOURCE_VERSION(info) = (event->data.l[1] >> 24);
+ XDND_AWARE_VIEW(info) = toplevel;
updateSourceWindow(info, event);
- /* store xdnd version for source */
- info->protocolVersion = (event->data.l[1] >> 24);
-
+/*
+ if (event->data.l[1] & 1)
+ /* XdndTypeList property is available */
+/* XDND_SOURCE_TYPES(info) = getTypesFromTypeList(scr,
XDND_SOURCE_WIN(info));
+ else
+ XDND_SOURCE_TYPES(info) = getTypesFromThreeTypes(scr, event);
+*/
XDND_SOURCE_TYPES(info) = getTypesFromThreeTypes(scr, event);
/* to use if the 3 types are not enough */
@@ -383,45 +376,30 @@
}
-static void
-cancelDrop(WMView *destView, WMDraggingInfo *info);
-
-static void
-suspendDropAuthorization(WMView *destView, WMDraggingInfo *info);
-
-
void
- W_DragDestinationStorePositionMsgInfo(WMDraggingInfo *info,
- WMView *toplevel,
XClientMessageEvent *event)
+W_DragDestinationStorePositionMsgInfo(WMDraggingInfo *info,
+ WMView *toplevel, XClientMessageEvent
*event)
{
int x = event->data.l[2] >> 16;
int y = event->data.l[2] & 0xffff;
- WMView *oldDestView;
WMView *newDestView;
- newDestView = findXdndViewInToplevel(toplevel, x, y);
+ newDestView = findDestinationViewInToplevel(toplevel, x, y);
if (XDND_DEST_INFO(info) == NULL) {
- initDestinationDragInfo(info);
+ initDestinationDragInfo(info, newDestView);
+ XDND_AWARE_VIEW(info) = toplevel;
updateSourceWindow(info, event);
- XDND_DEST_VIEW(info) = newDestView;
- }
- else {
- oldDestView = XDND_DEST_VIEW(info);
-
- if (newDestView != oldDestView) {
- if (oldDestView != NULL) {
- suspendDropAuthorization(oldDestView, info);
- XDND_DEST_STATE(info) = dropNotAllowedState;
- }
-
+ } else {
+ if (newDestView != XDND_DEST_VIEW(info)) {
updateSourceWindow(info, event);
XDND_DEST_VIEW(info) = newDestView;
+ XDND_SOURCE_ACTION_CHANGED(info) = False;
- if (newDestView != NULL) {
- if (XDND_DEST_STATE(info) != waitEnterState)
- XDND_DEST_STATE(info) = idleState;
- }
+ if (XDND_DEST_STATE(info) != waitEnterState)
+ XDND_DEST_STATE(info) = idleState;
+ } else {
+ XDND_SOURCE_ACTION_CHANGED(info) = (XDND_SOURCE_ACTION(info) !=
event->data.l[4]);
}
}
@@ -437,27 +415,62 @@
/* send a DnD message to the source window */
static void
-sendDnDClientMessage(WMView *destView, Atom message,
+sendDnDClientMessage(WMDraggingInfo *info, Atom message,
unsigned long data1,
unsigned long data2,
unsigned long data3,
unsigned long data4)
{
- WMScreen *scr = W_VIEW_SCREEN(destView);
- WMDraggingInfo *info = &scr->dragInfo;
+ if (! W_SendDnDClientMessage(W_VIEW_SCREEN(XDND_AWARE_VIEW(info))->display,
+ XDND_SOURCE_WIN(info),
+ message,
+ WMViewXID(XDND_AWARE_VIEW(info)),
+ data1,
+ data2,
+ data3,
+ data4)) {
+ /* drop failed */
+ W_DragDestinationInfoClear(info);
+ }
+}
- if (XDND_DEST_INFO(info) != NULL) {
- if (! W_SendDnDClientMessage(scr->display,
- XDND_SOURCE_WIN(info),
- message,
- WMViewXID(destView),
- data1,
- data2,
- data3,
- data4)) {
- /* drop failed */
- W_DragDestinationInfoClear(info);
- }
+
+/* send a xdndStatus message to the source, with position and size
+ of the destination if it has no subwidget (requesting a position message
+ on every move otherwise) */
+static void
+sendStatusMessage(WMView *destView, WMDraggingInfo *info, Atom action)
+{
+ unsigned long data1;
+
+ data1 = (action == None) ? 0 : 1;
+
+ if (destView->childrenList == NULL) {
+ WMScreen *scr = W_VIEW_SCREEN(destView);
+ int destX, destY;
+ WMSize destSize = WMGetViewSize(destView);
+ Window foo;
+
+ XTranslateCoordinates(scr->display, WMViewXID(destView), scr->rootWin,
+ 0, 0, &destX, &destY,
+ &foo);
+
+ sendDnDClientMessage(info,
+ W_VIEW_SCREEN(destView)->xdndStatusAtom,
+ data1,
+ (destX << 16)|destY,
+ (destSize.width << 16)|destSize.height,
+ action);
+ } else {
+ /* set bit 1 to request explicitly position message on every move */
+ data1 = data1 | 2;
+
+ sendDnDClientMessage(info,
+ W_VIEW_SCREEN(destView)->xdndStatusAtom,
+ data1,
+ 0,
+ 0,
+ action);
}
}
@@ -534,31 +547,26 @@
static void
cancelDrop(WMView *destView, WMDraggingInfo *info)
{
- /* send XdndStatus with action None */
- sendDnDClientMessage(destView,
- W_VIEW_SCREEN(destView)->xdndStatusAtom,
- 0, 0, 0, None);
+ sendStatusMessage(destView, info, None);
concludeDrop(destView);
freeDestinationViewInfos(info);
}
-/* suspend drop, when dragged icon enter an unaware subview of destView */
+/* suspend drop, when dragged icon enter an unregistered view
+ or a register view that doesn't accept the drop */
static void
suspendDropAuthorization(WMView *destView, WMDraggingInfo *info)
{
- /* free datas that depend on destination behaviour */
- /* (in short: only keep source's types) */
+ sendStatusMessage(destView, info, None);
+
+ /* Free datas that depend on destination behaviour */
if (XDND_DROP_DATAS(info) != NULL) {
WMFreeArray(XDND_DROP_DATAS(info));
XDND_DROP_DATAS(info) = NULL;
}
+
XDND_REQUIRED_TYPES(info) = NULL;
-
- /* send XdndStatus with action None */
- sendDnDClientMessage(destView,
- W_VIEW_SCREEN(destView)->xdndStatusAtom,
- 0, 0, 0, None);
}
@@ -566,14 +574,10 @@
void
W_DragDestinationCancelDropOnEnter(WMView *toplevel, WMDraggingInfo *info)
{
- if (XDND_DEST_VIEW_STORED(info))
+ if (XDND_DEST_VIEW_IS_REGISTERED(info))
cancelDrop(XDND_DEST_VIEW(info), info);
- else {
- /* send XdndStatus with action None */
- sendDnDClientMessage(toplevel,
- W_VIEW_SCREEN(toplevel)->xdndStatusAtom,
- 0, 0, 0, None);
- }
+ else
+ sendStatusMessage(toplevel, info, None);
W_DragDestinationInfoClear(info);
}
@@ -582,7 +586,7 @@
static void
finishDrop(WMView *destView, WMDraggingInfo *info)
{
- sendDnDClientMessage(destView,
+ sendDnDClientMessage(info,
W_VIEW_SCREEN(destView)->xdndFinishedAtom,
0, 0, 0, 0);
concludeDrop(destView);
@@ -603,31 +607,6 @@
}
-/* send the action that can be performed,
- and the limits outside wich the source must re-send
- its position and action */
-static void
-sendAllowedAction(WMView *destView, Atom action)
-{
- WMScreen *scr = W_VIEW_SCREEN(destView);
- /* // WMPoint destPos = WMGetViewScreenPosition(destView); */
- WMSize destSize = WMGetViewSize(destView);
- int destX, destY;
- Window foo;
-
- XTranslateCoordinates(scr->display, scr->rootWin, WMViewXID(destView),
- 0, 0, &destX, &destY,
- &foo);
-
- sendDnDClientMessage(destView,
- scr->xdndStatusAtom,
- 1,
- (destX << 16)|destY,
- (destSize.width << 16)|destSize.height,
- action);
-}
-
-
static void*
checkActionAllowed(WMView *destView, WMDraggingInfo* info)
{
@@ -639,9 +618,10 @@
return dropNotAllowedState;
}
- sendAllowedAction(destView, XDND_DEST_ACTION(info));
+ sendStatusMessage(destView, info, XDND_DEST_ACTION(info));
return dropAllowedState;
}
+
static void*
checkDropAllowed(WMView *destView, XClientMessageEvent *event,
@@ -670,6 +650,7 @@
return checkActionAllowed(destView, info);
}
+
static WMPoint*
getDropLocationInView(WMView *view)
{
@@ -689,6 +670,7 @@
return location;
}
+
static void
callPerformDragOperation(WMView *destView, WMDraggingInfo *info)
@@ -721,20 +703,16 @@
WMDraggingInfo *info;
wwarning("delay for drag source response expired");
- if (view != NULL) {
- info = &(W_VIEW_SCREEN(view)->dragInfo);
- if (XDND_DEST_VIEW_STORED(info))
- cancelDrop(view, info);
- else {
- /* send XdndStatus with action None */
- sendDnDClientMessage(view,
- W_VIEW_SCREEN(view)->xdndStatusAtom,
- 0, 0, 0, None);
- }
+ info = &(W_VIEW_SCREEN(view)->dragInfo);
+ if (XDND_DEST_VIEW_IS_REGISTERED(info))
+ cancelDrop(view, info);
+ else {
+ sendStatusMessage(view, info, None);
+ }
- W_DragDestinationInfoClear(info);
- }
+ W_DragDestinationInfoClear(info);
}
+
void
W_DragDestinationStopTimer()
@@ -745,21 +723,17 @@
}
}
+
void
W_DragDestinationStartTimer(WMDraggingInfo *info)
{
W_DragDestinationStopTimer();
- if (XDND_DEST_STATE(info) != idleState
- || XDND_DEST_VIEW(info) == NULL) {
- /* note: info->destView == NULL means :
- Enter message has been received, waiting for Position message */
-
+ if (XDND_DEST_STATE(info) != idleState)
dndDestinationTimer = WMAddTimerHandler(
XDND_SOURCE_RESPONSE_MAX_DELAY,
dragSourceResponseTimeOut,
XDND_DEST_VIEW(info));
- }
}
/* ----- End of Destination timer ----- */
@@ -795,6 +769,7 @@
}
#endif
+
static void*
idleState(WMView *destView, XClientMessageEvent *event,
WMDraggingInfo *info)
@@ -802,21 +777,24 @@
WMScreen *scr;
Atom sourceMsg;
- scr = W_VIEW_SCREEN(destView);
- sourceMsg = event->message_type;
+ if (destView->dragDestinationProcs != NULL) {
+ scr = W_VIEW_SCREEN(destView);
+ sourceMsg = event->message_type;
- if (sourceMsg == scr->xdndPositionAtom) {
- destView->dragDestinationProcs->prepareForDragOperation(destView);
+ if (sourceMsg == scr->xdndPositionAtom) {
+ destView->dragDestinationProcs->prepareForDragOperation(destView);
- if (XDND_SOURCE_TYPES(info) != NULL) {
- /* enter message infos are available */
- return checkDropAllowed(destView, event, info);
+ if (XDND_SOURCE_TYPES(info) != NULL) {
+ /* enter message infos are available */
+ return checkDropAllowed(destView, event, info);
+ }
+
+ /* waiting for enter message */
+ return waitEnterState;
}
-
- /* waiting for enter message */
- return waitEnterState;
}
+ suspendDropAuthorization(destView, info);
return idleState;
}
@@ -881,6 +859,15 @@
return idleState;
}
+ if (sourceMsg == scr->xdndPositionAtom) {
+ if (XDND_SOURCE_ACTION_CHANGED(info)) {
+ return checkDropAllowed(destView, event, info);
+ } else {
+ sendStatusMessage(destView, info, None);
+ return dropNotAllowedState;
+ }
+ }
+
return dropNotAllowedState;
}
@@ -912,6 +899,15 @@
return idleState;
}
+ if (sourceMsg == scr->xdndPositionAtom) {
+ if (XDND_SOURCE_ACTION_CHANGED(info)) {
+ return checkDropAllowed(destView, event, info);
+ } else {
+ sendStatusMessage(destView, info, XDND_DEST_ACTION(info));
+ return dropAllowedState;
+ }
+ }
+
return dropAllowedState;
}
@@ -947,29 +943,30 @@
WMView *destView;
W_DndState* newState;
- if (XDND_DEST_VIEW_STORED(info)) {
- destView = XDND_DEST_VIEW(info);
- if (XDND_DEST_STATE(info) == NULL)
- XDND_DEST_STATE(info) = idleState;
+ wassertr(XDND_DEST_INFO(info) != NULL);
+ wassertr(XDND_DEST_VIEW(info) != NULL);
+
+ destView = XDND_DEST_VIEW(info);
+ if (XDND_DEST_STATE(info) == NULL)
+ XDND_DEST_STATE(info) = idleState;
#ifdef XDND_DEBUG
- printf("current dest state: %s\n",
- stateName(XDND_DEST_STATE(info)));
+ printf("current dest state: %s\n",
+ stateName(XDND_DEST_STATE(info)));
#endif
- newState = (W_DndState*) XDND_DEST_STATE(info)(destView, event, info);
+ newState = (W_DndState*) XDND_DEST_STATE(info)(destView, event, info);
#ifdef XDND_DEBUG
- printf("new dest state: %s\n", stateName(newState));
+ printf("new dest state: %s\n", stateName(newState));
#endif
- if (XDND_DEST_INFO(info) != NULL) {
- XDND_DEST_STATE(info) = newState;
- if (XDND_DEST_STATE(info) != idleState)
- W_DragDestinationStartTimer(info);
- }
+ if (XDND_DEST_INFO(info) != NULL) {
+ XDND_DEST_STATE(info) = newState;
+ if (XDND_DEST_STATE(info) != idleState)
+ W_DragDestinationStartTimer(info);
}
}
@@ -1104,7 +1101,7 @@
Process drop
dropDatas: datas (WMData*) required by destination (self)
(given in same order as returned by requiredDataTypes).
- A NULL data means it couldn't be retrivied.
+ A NULL data means it couldn't be retrieved.
Destroyed when drop ends.
operationList: if source operation is WDOperationAsk, contains
operations (and associated texts) that can be asked
diff -r 5bef22c8d8ee -r cc87d65fc6e2 WINGs/dragsource.c
--- a/WINGs/dragsource.c Sun Jan 22 11:20:57 2006 -0800
+++ b/WINGs/dragsource.c Sun Jan 22 12:33:19 2006 -0800
@@ -16,10 +16,10 @@
#define MIN_Y_MOVE_OFFSET 5
#define MAX_SLIDEBACK_ITER 15
-#define VERSION_INFO(dragInfo) dragInfo->protocolVersion
#define XDND_PROPERTY_FORMAT 32
#define XDND_ACTION_DESCRIPTION_FORMAT 8
+#define XDND_DEST_VERSION(dragInfo) dragInfo->protocolVersion
#define XDND_SOURCE_INFO(dragInfo) dragInfo->sourceInfo
#define XDND_DEST_WIN(dragInfo) dragInfo->sourceInfo->destinationWindow
#define XDND_SOURCE_ACTION(dragInfo) dragInfo->sourceAction
@@ -415,21 +415,25 @@
sendEnterMessage(WMDraggingInfo *info)
{
WMScreen *scr = sourceScreen(info);
- unsigned long data1;
+ unsigned long version;
- data1 = (VERSION_INFO(info) << 24)|1; /* 1: support of type list */
+ if (XDND_DEST_VERSION(info) > 2) {
+ if (XDND_DEST_VERSION(info) < XDND_VERSION)
+ version = XDND_DEST_VERSION(info);
+ else
+ version = XDND_VERSION;
+ } else {
+ version = 3;
+ }
return sendDnDClientMessage(info, scr->xdndEnterAtom,
- data1,
+ (version << 24) | 1, /* 1: support of type
list */
XDND_3_TYPES(info)[0],
XDND_3_TYPES(info)[1],
XDND_3_TYPES(info)[2]);
}
-/*
-// this functon doesn't return something in all cases.
-// control reaches end of non-void function. fix this -Dan */
static Bool
sendPositionMessage(WMDraggingInfo *info, WMPoint *mousePos)
{
@@ -440,7 +444,7 @@
if (mousePos->x < noPosZone->pos.x
|| mousePos->x > (noPosZone->pos.x + noPosZone->size.width)
|| mousePos->y < noPosZone->pos.y
- || mousePos->y > (noPosZone->pos.y + noPosZone->size.width)) {
+ || mousePos->y > (noPosZone->pos.y + noPosZone->size.height)) {
/* send position if out of zone defined by destination */
return sendDnDClientMessage(info, scr->xdndPositionAtom,
0,
@@ -448,14 +452,18 @@
XDND_TIMESTAMP(info),
XDND_SOURCE_ACTION(info));
}
- } else {
- /* send position on each move */
- return sendDnDClientMessage(info, scr->xdndPositionAtom,
- 0,
- mousePos->x<<16|mousePos->y,
- XDND_TIMESTAMP(info),
- XDND_SOURCE_ACTION(info));
+
+ /* Nothing to send, always succeed */
+ return True;
+
}
+
+ /* send position on each move */
+ return sendDnDClientMessage(info, scr->xdndPositionAtom,
+ 0,
+ mousePos->x<<16|mousePos->y,
+ XDND_TIMESTAMP(info),
+ XDND_SOURCE_ACTION(info));
}
@@ -846,6 +854,30 @@
static void
+storeDestinationProtocolVersion(WMDraggingInfo *info)
+{
+ Atom type;
+ int format;
+ unsigned long count, remain;
+ unsigned char *winXdndVersion;
+ WMScreen *scr = W_VIEW_SCREEN(XDND_SOURCE_VIEW(info));
+
+ wassertr(XDND_DEST_WIN(info) != None);
+
+ if (XGetWindowProperty(scr->display, XDND_DEST_WIN(info),
+ scr->xdndAwareAtom,
+ 0, 1, False, XA_ATOM, &type, &format,
+ &count, &remain, &winXdndVersion) == Success) {
+ XDND_DEST_VERSION(info) = *winXdndVersion;
+ XFree(winXdndVersion);
+ } else {
+ XDND_DEST_VERSION(info) = 0;
+ wwarning("failed to read XDND version of drop target");
+ }
+}
+
+
+static void
initMotionProcess(WMView *view, WMDraggingInfo *info,
XEvent *event, WMPoint *startLocation)
{
@@ -878,9 +910,8 @@
static void
-processMotion(WMDraggingInfo *info, Window windowUnderDrag, WMPoint *mousePos)
+processMotion(WMDraggingInfo *info, WMPoint *mousePos)
{
- /* // WMScreen *scr = sourceScreen(info); */
Window newDestination = findDestination(info, mousePos);
W_DragSourceStopTimer();
@@ -894,20 +925,24 @@
}
XDND_DEST_WIN(info) = newDestination;
- XDND_SOURCE_STATE(info) = idleState;
XDND_DEST_ACTION(info) = None;
XDND_NO_POS_ZONE(info).size.width = 0;
XDND_NO_POS_ZONE(info).size.height = 0;
if (newDestination != None) {
/* entering a xdnd window */
+ XDND_SOURCE_STATE(info) = idleState;
+ storeDestinationProtocolVersion(info);
+
if (! sendEnterMessage(info)) {
XDND_DEST_WIN(info) = None;
return;
}
W_DragSourceStartTimer(info);
- }
+ } else {
+ XDND_SOURCE_STATE(info) = NULL;
+ }
} else {
if (XDND_DEST_WIN(info) != None) {
if (! sendPositionMessage(info, mousePos)) {
@@ -1010,9 +1045,7 @@
mouseLocation.y - XDND_MOUSE_OFFSET(info).y;
refreshDragImage(view, info);
- processMotion(info,
- event->xmotion.window,
- &mouseLocation);
+ processMotion(info, &mouseLocation);
}
}
}
@@ -1041,7 +1074,7 @@
printf("Xdnd status message:\n");
if (statusEvent->data.l[1] & 0x2UL)
- printf("send position on every move\n");
+ printf("\tsend position on every move\n");
else {
int x, y, w, h;
x = statusEvent->data.l[2] >> 16;
@@ -1049,15 +1082,15 @@
w = statusEvent->data.l[3] >> 16;
h = statusEvent->data.l[3] & 0xFFFFL;
- printf("send position out of ((%d,%d) , (%d,%d))\n",
+ printf("\tsend position out of ((%d,%d) , (%d,%d))\n",
x, y, x+w, y+h);
}
if (statusEvent->data.l[1] & 0x1L)
- printf("allowed action: %s\n",
+ printf("\tallowed action: %s\n",
XGetAtomName(dpy, statusEvent->data.l[4]));
else
- printf("no action allowed\n");
+ printf("\tno action allowed\n");
}
#endif
@@ -1231,23 +1264,28 @@
W_DndState* newState;
if (XDND_SOURCE_VIEW_STORED(info)) {
- view = XDND_SOURCE_VIEW(info);
+ if (XDND_SOURCE_STATE(info) != NULL) {
+ view = XDND_SOURCE_VIEW(info);
#ifdef XDND_DEBUG
- printf("current source state: %s\n",
- stateName(XDND_SOURCE_STATE(info)));
+ printf("current source state: %s\n",
+ stateName(XDND_SOURCE_STATE(info)));
#endif
- newState = (W_DndState*) XDND_SOURCE_STATE(info)(view, event, info);
+ newState = (W_DndState*) XDND_SOURCE_STATE(info)(view, event,
info);
#ifdef XDND_DEBUG
- printf("new source state: %s\n", stateName(newState));
+ printf("new source state: %s\n", stateName(newState));
#endif
- if (newState != NULL)
- XDND_SOURCE_STATE(info) = newState;
- /* else drop finished, and info has been flushed */
+ if (newState != NULL)
+ XDND_SOURCE_STATE(info) = newState;
+ /* else drop finished, and info has been flushed */
+ }
+
+ } else {
+ wwarning("received DnD message without having a target");
}
}
--
To unsubscribe, send mail to [EMAIL PROTECTED]