diff -ur WindowMaker-0.92.0/WINGs/dragcommon.c WindowMaker-0.92.0-patch/WINGs/dragcommon.c --- WindowMaker-0.92.0/WINGs/dragcommon.c 2004-10-28 11:25:23.000000000 +0200 +++ WindowMaker-0.92.0-patch/WINGs/dragcommon.c 2005-04-18 19:03:07.710964296 +0200 @@ -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 -ur WindowMaker-0.92.0/WINGs/dragdestination.c WindowMaker-0.92.0-patch/WINGs/dragdestination.c --- WindowMaker-0.92.0/WINGs/dragdestination.c 2004-10-28 11:25:36.000000000 +0200 +++ WindowMaker-0.92.0-patch/WINGs/dragdestination.c 2005-04-18 19:03:07.712963992 +0200 @@ -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,22 +138,29 @@ 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; - } - - /* 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; - } + 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); } - - 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); + XDND_REQUIRED_TYPES(info) = NULL; } @@ -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,10 +618,11 @@ return dropNotAllowedState; } - sendAllowedAction(destView, XDND_DEST_ACTION(info)); + sendStatusMessage(destView, info, XDND_DEST_ACTION(info)); return dropAllowedState; } + static void* checkDropAllowed(WMView *destView, XClientMessageEvent *event, WMDraggingInfo* info) @@ -670,6 +650,7 @@ return checkActionAllowed(destView, info); } + static WMPoint* getDropLocationInView(WMView *view) { @@ -690,6 +671,7 @@ return location; } + static void callPerformDragOperation(WMView *destView, WMDraggingInfo *info) { @@ -721,21 +703,17 @@ 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); - } - - W_DragDestinationInfoClear(info); + info = &(W_VIEW_SCREEN(view)->dragInfo); + if (XDND_DEST_VIEW_IS_REGISTERED(info)) + cancelDrop(view, info); + else { + sendStatusMessage(view, info, None); } + + 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 (sourceMsg == scr->xdndPositionAtom) { - destView->dragDestinationProcs->prepareForDragOperation(destView); + if (destView->dragDestinationProcs != NULL) { + scr = W_VIEW_SCREEN(destView); + sourceMsg = event->message_type; + + 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 -ur WindowMaker-0.92.0/WINGs/dragsource.c WindowMaker-0.92.0-patch/WINGs/dragsource.c --- WindowMaker-0.92.0/WINGs/dragsource.c 2004-10-28 11:29:59.000000000 +0200 +++ WindowMaker-0.92.0-patch/WINGs/dragsource.c 2005-04-18 19:03:07.713963840 +0200 @@ -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"); } } diff -ur WindowMaker-0.92.0/WINGs/WINGs/WINGsP.h WindowMaker-0.92.0-patch/WINGs/WINGs/WINGsP.h --- WindowMaker-0.92.0/WINGs/WINGs/WINGsP.h 2004-10-30 08:32:50.000000000 +0200 +++ WindowMaker-0.92.0-patch/WINGs/WINGs/WINGsP.h 2005-04-18 19:03:21.299898464 +0200 @@ -29,7 +29,7 @@ #define SCROLLER_WIDTH 20 -#define XDND_VERSION 4 +#define XDND_VERSION 3 typedef struct W_Application { @@ -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;