1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include "xdnd.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 static Atom XdndAware;
30 static Atom XdndSelection;
31 static Atom XdndStatus;
32 static Atom XdndActionCopy;
33 static Atom XdndFinished;
34
35 static Window src;
36
37 static Atom selType;
38
39 static int canDrop;
40
41 XtCallbackProc dropCallback;
42 XtPointer dropData;
43
44 static void checkSelectionValue(Widget w, XtPointer clientData, Atom *selType,
45 Atom *type, XtPointer value,
unsigned long *length,
int *format)
46 {
47 if(value) {
48 canDrop =
1;
49 XtFree(value);
50 }
51 }
52
53 static void getSelectionValue(Widget w, XtPointer clientData, Atom *selType,
54 Atom *type, XtPointer value,
unsigned long *length,
int *format)
55 {
56 if(value) {
57 if(dropCallback) {
58 dropCallback(w, value, dropData);
59 }
60 XtFree(value);
61
62
63 if(src !=
0) {
64 XEvent msg;
65 memset(&msg,
0,
sizeof(XEvent));
66 msg.xany.type = ClientMessage;
67 msg.xany.display = XtDisplay(w);
68 msg.xclient.window = src;
69 msg.xclient.message_type = XdndFinished;
70 msg.xclient.format =
32;
71 msg.xclient.data.l[
0] = XtWindow(w);
72 XSendEvent(XtDisplay(w), msg.xclient.window,
0,
0, &msg);
73 src =
0;
74 }
75 }
76 }
77
78 static void xdnd_enter(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
79
80 XtGetSelectionValue(w, XdndSelection, selType, checkSelectionValue,
NULL,
0);
81 }
82
83 static void xdnd_position(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
84
85
86 src = event->xclient.data.l[
0];
87
88 XEvent msg;
89 memset(&msg,
0,
sizeof(XEvent));
90 msg.xany.type = ClientMessage;
91 msg.xany.display = XtDisplay(w);
92 msg.xclient.window = src;
93 msg.xclient.message_type = XdndStatus;
94 msg.xclient.format =
32;
95 msg.xclient.data.l[
0] = XtWindow(w);
96 msg.xclient.data.l[
1] = canDrop;
97 msg.xclient.data.l[
4] = XdndActionCopy;
98 XSendEvent(XtDisplay(w), msg.xclient.window,
0,
0, &msg);
99 }
100
101 static void xdnd_drop(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
102
103
104 XtGetSelectionValue(w, XdndSelection, selType, getSelectionValue,
NULL,
0);
105
106 canDrop =
0;
107 }
108
109 static void xdnd_leave(Widget w, XEvent *event, String *args, Cardinal *nArgs) {
110
111 canDrop =
0;
112 }
113
114 static XtActionsRec xdndactions[] = {
115 {
"xdnd_enter", xdnd_enter},
116 {
"xdnd_position", xdnd_position},
117 {
"xdnd_drop", xdnd_drop},
118 {
"xdnd_leave", xdnd_leave}
119 };
120
121
122 void XdndInit(
123 Display *dpy,
124 XtAppContext app,
125 XtCallbackProc dropCB,
126 XtPointer dropCBData)
127 {
128
129 XdndAware = XInternAtom(dpy,
"XdndAware", False);
130 XdndSelection = XInternAtom(dpy,
"XdndSelection", False);
131 XdndStatus = XInternAtom(dpy,
"XdndStatus", False);
132 XdndActionCopy = XInternAtom(dpy,
"XdndActionCopy", False);
133 XdndFinished = XInternAtom(dpy,
"XdndFinished", False);
134 selType = XInternAtom(dpy,
"text/uri-list", False);
135
136 XtAppAddActions(
137 app,
138 xdndactions,
139 sizeof(xdndactions) /
sizeof(XtActionsRec));
140
141 dropCallback = dropCB;
142 dropData = dropCBData;
143 }
144
145
146
147 void XdndEnable(Widget w) {
148 long version =
4;
149 XChangeProperty(
150 XtDisplay(w),
151 XtWindow(w),
152 XdndAware,
153 XA_ATOM,
154 32,
155 PropModeReplace,
156 (XtPointer)&version,
157 1);
158
159 if(XtIsShell(w)) {
160 XtOverrideTranslations(w, XtParseTranslationTable(
161 "<Message>XdndEnter: xdnd_enter()\n"
162 "<Message>XdndPosition: xdnd_position()\n"
163 "<Message>XdndDrop: xdnd_drop()\n"
164 "<Message>XdndLeave: xdnd_leave()\n"));
165 }
166 }
167