drag-n-drop.c (4285B)
1 const char XdndVersion = 5; 2 3 void 4 xdndsel(XEvent *e) 5 { 6 char* data; 7 unsigned long result; 8 9 Atom actualType; 10 int32_t actualFormat; 11 unsigned long bytesAfter; 12 XEvent reply = { ClientMessage }; 13 14 reply.xclient.window = xw.XdndSourceWin; 15 reply.xclient.format = 32; 16 reply.xclient.data.l[0] = (long) xw.win; 17 reply.xclient.data.l[2] = 0; 18 reply.xclient.data.l[3] = 0; 19 20 XGetWindowProperty((Display*) xw.dpy, e->xselection.requestor, 21 e->xselection.property, 0, LONG_MAX, False, 22 e->xselection.target, &actualType, &actualFormat, &result, 23 &bytesAfter, (unsigned char**) &data); 24 25 if (result == 0) 26 return; 27 28 if (data) { 29 xdndpastedata(data); 30 XFree(data); 31 } 32 33 if (xw.XdndSourceVersion >= 2) { 34 reply.xclient.message_type = xw.XdndFinished; 35 reply.xclient.data.l[1] = result; 36 reply.xclient.data.l[2] = xw.XdndActionCopy; 37 38 XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, NoEventMask, 39 &reply); 40 XFlush((Display*) xw.dpy); 41 } 42 } 43 44 int 45 xdndurldecode(char *src, char *dest) 46 { 47 char c; 48 int i = 0; 49 50 while (*src) { 51 if (*src == '%' && HEX_TO_INT(src[1]) != -1 && HEX_TO_INT(src[2]) != -1) { 52 /* handle %xx escape sequences in url e.g. %20 == ' ' */ 53 c = (char)((HEX_TO_INT(src[1]) << 4) | HEX_TO_INT(src[2])); 54 src += 3; 55 } else { 56 c = *src++; 57 } 58 if (strchr(xdndescchar, c) != NULL) { 59 *dest++ = '\\'; 60 i++; 61 } 62 *dest++ = c; 63 i++; 64 } 65 *dest++ = ' '; 66 *dest = '\0'; 67 return i + 1; 68 } 69 70 void 71 xdndpastedata(char *data) 72 { 73 char *pastedata, *t; 74 int i = 0; 75 76 pastedata = (char *)malloc(strlen(data) * 2 + 1); 77 *pastedata = '\0'; 78 79 t = strtok(data, "\n\r"); 80 while(t != NULL) { 81 /* Remove 'file://' prefix if it exists */ 82 if (strncmp(data, "file://", 7) == 0) { 83 t += 7; 84 } 85 i += xdndurldecode(t, pastedata + i); 86 t = strtok(NULL, "\n\r"); 87 } 88 89 xsetsel(pastedata); 90 selpaste(0); 91 } 92 93 void 94 xdndenter(XEvent *e) 95 { 96 unsigned long count; 97 Atom* formats; 98 Atom real_formats[6]; 99 Bool list; 100 Atom actualType; 101 int32_t actualFormat; 102 unsigned long bytesAfter; 103 unsigned long i; 104 105 list = e->xclient.data.l[1] & 1; 106 107 if (list) { 108 XGetWindowProperty((Display*) xw.dpy, 109 xw.XdndSourceWin, 110 xw.XdndTypeList, 111 0, 112 LONG_MAX, 113 False, 114 4, 115 &actualType, 116 &actualFormat, 117 &count, 118 &bytesAfter, 119 (unsigned char**) &formats); 120 } else { 121 count = 0; 122 123 if (e->xclient.data.l[2] != None) 124 real_formats[count++] = e->xclient.data.l[2]; 125 if (e->xclient.data.l[3] != None) 126 real_formats[count++] = e->xclient.data.l[3]; 127 if (e->xclient.data.l[4] != None) 128 real_formats[count++] = e->xclient.data.l[4]; 129 130 formats = real_formats; 131 } 132 133 for (i = 0; i < count; i++) { 134 if (formats[i] == xw.XtextUriList || formats[i] == xw.XtextPlain) { 135 xw.XdndSourceFormat = formats[i]; 136 break; 137 } 138 } 139 140 if (list) 141 XFree(formats); 142 } 143 144 void 145 xdndpos(XEvent *e) 146 { 147 const int32_t xabs = (e->xclient.data.l[2] >> 16) & 0xffff; 148 const int32_t yabs = (e->xclient.data.l[2]) & 0xffff; 149 Window dummy; 150 int32_t xpos, ypos; 151 XEvent reply = { ClientMessage }; 152 153 reply.xclient.window = xw.XdndSourceWin; 154 reply.xclient.format = 32; 155 reply.xclient.data.l[0] = (long) xw.win; 156 reply.xclient.data.l[2] = 0; 157 reply.xclient.data.l[3] = 0; 158 159 XTranslateCoordinates((Display*) xw.dpy, 160 XDefaultRootWindow((Display*) xw.dpy), 161 (Window) xw.win, 162 xabs, yabs, 163 &xpos, &ypos, 164 &dummy); 165 166 reply.xclient.message_type = xw.XdndStatus; 167 168 if (xw.XdndSourceFormat) { 169 reply.xclient.data.l[1] = 1; 170 if (xw.XdndSourceVersion >= 2) 171 reply.xclient.data.l[4] = xw.XdndActionCopy; 172 } 173 174 XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, NoEventMask, 175 &reply); 176 XFlush((Display*) xw.dpy); 177 } 178 179 void 180 xdnddrop(XEvent *e) 181 { 182 Time time = CurrentTime; 183 XEvent reply = { ClientMessage }; 184 185 reply.xclient.window = xw.XdndSourceWin; 186 reply.xclient.format = 32; 187 reply.xclient.data.l[0] = (long) xw.win; 188 reply.xclient.data.l[2] = 0; 189 reply.xclient.data.l[3] = 0; 190 191 if (xw.XdndSourceFormat) { 192 if (xw.XdndSourceVersion >= 1) 193 time = e->xclient.data.l[2]; 194 195 XConvertSelection((Display*) xw.dpy, xw.XdndSelection, 196 xw.XdndSourceFormat, xw.XdndSelection, (Window) xw.win, time); 197 } else if (xw.XdndSourceVersion >= 2) { 198 reply.xclient.message_type = xw.XdndFinished; 199 200 XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, 201 False, NoEventMask, &reply); 202 XFlush((Display*) xw.dpy); 203 } 204 }