#include "xdnd.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static Atom XdndAware;
static Atom XdndSelection;
static Atom XdndStatus;
static Atom XdndActionCopy;
static Atom XdndFinished;
static Window src;
static Atom selType;
static int canDrop;
XtCallbackProc dropCallback;
XtPointer dropData;
static void checkSelectionValue(Widget w, XtPointer clientData, Atom *selType,
Atom *type, XtPointer value,
unsigned long *length,
int *format)
{
if(value) {
canDrop =
1;
XtFree(value);
}
}
static void getSelectionValue(Widget w, XtPointer clientData, Atom *selType,
Atom *type, XtPointer value,
unsigned long *length,
int *format)
{
if(value) {
if(dropCallback) {
dropCallback(w, value, dropData);
}
XtFree(value);
if(src !=
0) {
XEvent msg;
memset(&msg,
0,
sizeof(XEvent));
msg.xany.type = ClientMessage;
msg.xany.display = XtDisplay(w);
msg.xclient.window = src;
msg.xclient.message_type = XdndFinished;
msg.xclient.format =
32;
msg.xclient.data.l[
0] = XtWindow(w);
XSendEvent(XtDisplay(w), msg.xclient.window,
0,
0, &msg);
src =
0;
}
}
}
static void xdnd_enter(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
XtGetSelectionValue(w, XdndSelection, selType, checkSelectionValue,
NULL,
0);
}
static void xdnd_position(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
src = event->xclient.data.l[
0];
XEvent msg;
memset(&msg,
0,
sizeof(XEvent));
msg.xany.type = ClientMessage;
msg.xany.display = XtDisplay(w);
msg.xclient.window = src;
msg.xclient.message_type = XdndStatus;
msg.xclient.format =
32;
msg.xclient.data.l[
0] = XtWindow(w);
msg.xclient.data.l[
1] = canDrop;
msg.xclient.data.l[
4] = XdndActionCopy;
XSendEvent(XtDisplay(w), msg.xclient.window,
0,
0, &msg);
}
static void xdnd_drop(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
XtGetSelectionValue(w, XdndSelection, selType, getSelectionValue,
NULL,
0);
canDrop =
0;
}
static void xdnd_leave(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
canDrop =
0;
}
static XtActionsRec xdndactions[] = {
{
"xdnd_enter", xdnd_enter},
{
"xdnd_position", xdnd_position},
{
"xdnd_drop", xdnd_drop},
{
"xdnd_leave", xdnd_leave}
};
void XdndInit(
Display *dpy,
XtAppContext app,
XtCallbackProc dropCB,
XtPointer dropCBData)
{
XdndAware = XInternAtom(dpy,
"XdndAware", False);
XdndSelection = XInternAtom(dpy,
"XdndSelection", False);
XdndStatus = XInternAtom(dpy,
"XdndStatus", False);
XdndActionCopy = XInternAtom(dpy,
"XdndActionCopy", False);
XdndFinished = XInternAtom(dpy,
"XdndFinished", False);
selType = XInternAtom(dpy,
"text/uri-list", False);
XtAppAddActions(
app,
xdndactions,
sizeof(xdndactions) /
sizeof(XtActionsRec));
dropCallback = dropCB;
dropData = dropCBData;
}
void XdndEnable(Widget w) {
long version =
4;
XChangeProperty(
XtDisplay(w),
XtWindow(w),
XdndAware,
XA_ATOM,
32,
PropModeReplace,
(XtPointer)&version,
1);
if(XtIsShell(w)) {
XtOverrideTranslations(w, XtParseTranslationTable(
"<Message>XdndEnter: xdnd_enter()\n"
"<Message>XdndPosition: xdnd_position()\n"
"<Message>XdndDrop: xdnd_drop()\n"
"<Message>XdndLeave: xdnd_leave()\n"));
}
}