[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 13 of 22] - updated the XDND code in WINGs to work with GDK based applications



# HG changeset patch
# User Dan Pascu <dan@ag-projects.com>
# 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 <sreynal@nerim.net>)
- 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 <sreynal@nerim.net>)
(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 <martin.frydl@systinet.com>)
 - updated estonian translation (Ivar Smolin <okul@linux.ee>)
+- 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 <sreynal@nerim.net>)
+- 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 <sreynal@nerim.net>)
 
 
 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 <sreynal@nerim.net>)
+- 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 <sreynal@nerim.net>)
+
+
 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 wmaker-dev-unsubscribe@lists.windowmaker.info.