X-Git-Url: https://repo.or.cz/w/wmaker-crm.git/blobdiff_plain/59fc927dc9f183802621138534fa6eaafe5593ba..688a56e8ab67b56550e2874d9d7423f0d435bfd9:/WINGs/dragcommon.c diff --git a/WINGs/dragcommon.c b/WINGs/dragcommon.c dissimilarity index 93% index be468e54..feb2e87a 100644 --- a/WINGs/dragcommon.c +++ b/WINGs/dragcommon.c @@ -1,290 +1,255 @@ - - -#include "WINGsP.h" - -#define XDND_SOURCE_VERSION(dragInfo) dragInfo->protocolVersion -#define XDND_DEST_INFO(dragInfo) dragInfo->destInfo -#define XDND_DEST_VIEW(dragInfo) dragInfo->destInfo->destView - - -static Bool _WindowExists; - - -Atom -W_OperationToAction(WMScreen *scr, WMDragOperationType operation) -{ - switch (operation) { - case WDOperationNone: - return None; - - case WDOperationCopy: - return scr->xdndActionCopy; - - case WDOperationMove: - return scr->xdndActionMove; - - case WDOperationLink: - return scr->xdndActionLink; - - case WDOperationAsk: - return scr->xdndActionAsk; - - case WDOperationPrivate: - return scr->xdndActionPrivate; - - default: - return None; - } -} - - -WMDragOperationType -W_ActionToOperation(WMScreen *scr, Atom action) -{ - if (action == scr->xdndActionCopy) { - return WDOperationCopy; - - } else if (action == scr->xdndActionMove) { - return WDOperationMove; - - } else if (action == scr->xdndActionLink) { - return WDOperationLink; - - } else if (action == scr->xdndActionAsk) { - return WDOperationAsk; - - } else if (action == scr->xdndActionPrivate) { - return WDOperationPrivate; - - } else if (action == None) { - - return WDOperationNone; - } else { - char *tmp = XGetAtomName(scr->display, action); - - wwarning("unknown XDND action %s ", tmp); - XFree(tmp); - - return WDOperationCopy; - } -} - - -static void -freeDragOperationItem(void* item) -{ - wfree(item); -} - -WMArray* -WMCreateDragOperationArray(int initialSize) -{ - return WMCreateArrayWithDestructor(initialSize, freeDragOperationItem); -} - - -WMDragOperationItem* -WMCreateDragOperationItem(WMDragOperationType type, char* text) -{ - W_DragOperationItem *result = wmalloc(sizeof(W_DragOperationItem)); - - result->type = type; - result->text = text; - - return (WMDragOperationItem*) result; -} - -WMDragOperationType -WMGetDragOperationItemType(WMDragOperationItem* item) -{ - return ((W_DragOperationItem*)item)->type; -} - - -char* -WMGetDragOperationItemText(WMDragOperationItem* item) -{ - return ((W_DragOperationItem*)item)->text; -} - -static int -handleNoWindowXError(Display *dpy, XErrorEvent *errEvt) -{ - if (errEvt->error_code == BadWindow - || errEvt->error_code == BadDrawable) { - _WindowExists = False; - return Success; - } - - return errEvt->error_code; -} - - -static Bool -windowExists(Display *dpy, Window win) -{ - void* previousErrorHandler; - XWindowAttributes attr; - - XSynchronize(dpy, True); - previousErrorHandler = XSetErrorHandler(handleNoWindowXError); - _WindowExists = True; - - /* can generate BadDrawable or BadWindow */ - XGetWindowAttributes(dpy, win, &attr); - - XSetErrorHandler(previousErrorHandler); - XSynchronize(dpy, False); - return _WindowExists; -} - - -Bool -W_SendDnDClientMessage(Display *dpy, Window win, Atom message, - unsigned long data0, - unsigned long data1, - unsigned long data2, - unsigned long data3, - unsigned long data4) -{ - 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 */ - } - - ev.type = ClientMessage; - ev.xclient.message_type = message; - ev.xclient.format = 32; - ev.xclient.window = win; - ev.xclient.data.l[0] = data0; - ev.xclient.data.l[1] = data1; - ev.xclient.data.l[2] = data2; - ev.xclient.data.l[3] = data3; - ev.xclient.data.l[4] = data4; - - - XSendEvent(dpy, win, False, 0, &ev); - XFlush(dpy); - -#ifdef XDND_DEBUG - printf("sent\n"); -#endif - return True; /* message sent */ -} - - -static void -handleLeaveMessage(WMDraggingInfo *info) -{ - if (XDND_DEST_INFO(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)); - } - W_DragDestinationInfoClear(info); - } -} - - -void -W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event) -{ - WMScreen *scr = W_VIEW_SCREEN(toplevel); - WMDraggingInfo *info = &scr->dragInfo; - Atom messageType = event->message_type; - -#ifdef XDND_DEBUG - { - char* msgTypeName = XGetAtomName(scr->display, messageType); - - if (msgTypeName != NULL) - printf("event type = %s\n", msgTypeName); - else - printf("pb with event type !\n"); - } -#endif - - - /* Messages from destination to source */ - if (messageType == scr->xdndStatusAtom - || messageType == scr->xdndFinishedAtom) { - W_DragSourceStopTimer(); - W_DragSourceStateHandler(info, event); - return; - } - - /* Messages from source to destination */ - if (messageType == scr->xdndEnterAtom) { - Bool positionSent = (XDND_DEST_INFO(info) != NULL); - - W_DragDestinationStopTimer(); - W_DragDestinationStoreEnterMsgInfo(info, toplevel, event); - - /* 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; - } else { - W_DragDestinationStartTimer(info); - return; - } - } else { - wwarning("received dnd enter msg with unsupported version %i", - XDND_SOURCE_VERSION(info)); - W_DragDestinationCancelDropOnEnter(toplevel, info); - return; - } - } - - if (messageType == scr->xdndPositionAtom) { - W_DragDestinationStopTimer(); - W_DragDestinationStorePositionMsgInfo(info, toplevel, event); - W_DragDestinationStateHandler(info, event); - return; - } - - if (messageType == scr->xdndSelectionAtom - || messageType == scr->xdndDropAtom) { - W_DragDestinationStopTimer(); - W_DragDestinationStateHandler(info, event); - return; - } - - if (messageType == scr->xdndLeaveAtom) { - /* conclude drop operation, and clear dragging info */ - W_DragDestinationStopTimer(); - handleLeaveMessage(info); - } -} - - -/* called in destroyView (wview.c) */ -void -W_FreeViewXdndPart(WMView *view) -{ - WMUnregisterViewDraggedTypes(view); - - if (view->dragSourceProcs) - wfree(view->dragSourceProcs); - - if (view->dragDestinationProcs) - wfree(view->dragDestinationProcs); - - if (view->dragImage) - WMReleasePixmap(view->dragImage); -} - + +#include "WINGsP.h" + +#define XDND_SOURCE_VERSION(dragInfo) dragInfo->protocolVersion +#define XDND_DEST_INFO(dragInfo) dragInfo->destInfo +#define XDND_DEST_VIEW(dragInfo) dragInfo->destInfo->destView + +static Bool _WindowExists; + +Atom W_OperationToAction(WMScreen * scr, WMDragOperationType operation) +{ + switch (operation) { + case WDOperationNone: + return None; + + case WDOperationCopy: + return scr->xdndActionCopy; + + case WDOperationMove: + return scr->xdndActionMove; + + case WDOperationLink: + return scr->xdndActionLink; + + case WDOperationAsk: + return scr->xdndActionAsk; + + case WDOperationPrivate: + return scr->xdndActionPrivate; + + default: + return None; + } +} + +WMDragOperationType W_ActionToOperation(WMScreen * scr, Atom action) +{ + if (action == scr->xdndActionCopy) { + return WDOperationCopy; + + } else if (action == scr->xdndActionMove) { + return WDOperationMove; + + } else if (action == scr->xdndActionLink) { + return WDOperationLink; + + } else if (action == scr->xdndActionAsk) { + return WDOperationAsk; + + } else if (action == scr->xdndActionPrivate) { + return WDOperationPrivate; + + } else if (action == None) { + + return WDOperationNone; + } else { + char *tmp = XGetAtomName(scr->display, action); + + wwarning("unknown XDND action %s ", tmp); + XFree(tmp); + + return WDOperationCopy; + } +} + +static void freeDragOperationItem(void *item) +{ + wfree(item); +} + +WMArray *WMCreateDragOperationArray(int initialSize) +{ + return WMCreateArrayWithDestructor(initialSize, freeDragOperationItem); +} + +WMDragOperationItem *WMCreateDragOperationItem(WMDragOperationType type, char *text) +{ + W_DragOperationItem *result = wmalloc(sizeof(W_DragOperationItem)); + + result->type = type; + result->text = text; + + return (WMDragOperationItem *) result; +} + +WMDragOperationType WMGetDragOperationItemType(WMDragOperationItem * item) +{ + return ((W_DragOperationItem *) item)->type; +} + +char *WMGetDragOperationItemText(WMDragOperationItem * item) +{ + return ((W_DragOperationItem *) item)->text; +} + +static int handleNoWindowXError(Display * dpy, XErrorEvent * errEvt) +{ + if (errEvt->error_code == BadWindow || errEvt->error_code == BadDrawable) { + _WindowExists = False; + return Success; + } + + return errEvt->error_code; +} + +static Bool windowExists(Display * dpy, Window win) +{ + void *previousErrorHandler; + XWindowAttributes attr; + + XSynchronize(dpy, True); + previousErrorHandler = XSetErrorHandler(handleNoWindowXError); + _WindowExists = True; + + /* can generate BadDrawable or BadWindow */ + XGetWindowAttributes(dpy, win, &attr); + + XSetErrorHandler(previousErrorHandler); + XSynchronize(dpy, False); + return _WindowExists; +} + +Bool +W_SendDnDClientMessage(Display * dpy, Window win, Atom message, + unsigned long data0, + unsigned long data1, unsigned long data2, unsigned long data3, unsigned long data4) +{ + 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 */ + } + + ev.type = ClientMessage; + ev.xclient.message_type = message; + ev.xclient.format = 32; + ev.xclient.window = win; + ev.xclient.data.l[0] = data0; + ev.xclient.data.l[1] = data1; + ev.xclient.data.l[2] = data2; + ev.xclient.data.l[3] = data3; + ev.xclient.data.l[4] = data4; + + XSendEvent(dpy, win, False, 0, &ev); + XFlush(dpy); + +#ifdef XDND_DEBUG + printf("sent\n"); +#endif + return True; /* message sent */ +} + +static void handleLeaveMessage(WMDraggingInfo * info) +{ + if (XDND_DEST_INFO(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)); + } + W_DragDestinationInfoClear(info); + } +} + +void W_HandleDNDClientMessage(WMView * toplevel, XClientMessageEvent * event) +{ + WMScreen *scr = W_VIEW_SCREEN(toplevel); + WMDraggingInfo *info = &scr->dragInfo; + Atom messageType = event->message_type; + +#ifdef XDND_DEBUG + { + char *msgTypeName = XGetAtomName(scr->display, messageType); + + if (msgTypeName != NULL) + printf("event type = %s\n", msgTypeName); + else + printf("pb with event type !\n"); + } +#endif + + /* Messages from destination to source */ + if (messageType == scr->xdndStatusAtom || messageType == scr->xdndFinishedAtom) { + W_DragSourceStopTimer(); + W_DragSourceStateHandler(info, event); + return; + } + + /* Messages from source to destination */ + if (messageType == scr->xdndEnterAtom) { + Bool positionSent = (XDND_DEST_INFO(info) != NULL); + + W_DragDestinationStopTimer(); + W_DragDestinationStoreEnterMsgInfo(info, toplevel, event); + + /* 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; + } else { + W_DragDestinationStartTimer(info); + return; + } + } else { + wwarning("received dnd enter msg with unsupported version %i", XDND_SOURCE_VERSION(info)); + W_DragDestinationCancelDropOnEnter(toplevel, info); + return; + } + } + + if (messageType == scr->xdndPositionAtom) { + W_DragDestinationStopTimer(); + W_DragDestinationStorePositionMsgInfo(info, toplevel, event); + W_DragDestinationStateHandler(info, event); + return; + } + + if (messageType == scr->xdndSelectionAtom || messageType == scr->xdndDropAtom) { + W_DragDestinationStopTimer(); + W_DragDestinationStateHandler(info, event); + return; + } + + if (messageType == scr->xdndLeaveAtom) { + /* conclude drop operation, and clear dragging info */ + W_DragDestinationStopTimer(); + handleLeaveMessage(info); + } +} + +/* called in destroyView (wview.c) */ +void W_FreeViewXdndPart(WMView * view) +{ + WMUnregisterViewDraggedTypes(view); + + if (view->dragSourceProcs) + wfree(view->dragSourceProcs); + + if (view->dragDestinationProcs) + wfree(view->dragDestinationProcs); + + if (view->dragImage) + WMReleasePixmap(view->dragImage); +}