aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-03-31 17:21:37 +0800
committerPo Lu2022-03-31 17:21:37 +0800
commit1d4306a8a770cb73db3b39301ee41e15f9e3656f (patch)
treeb40831da1ca6a8aaf016e2d4e1c556d4ff22dfc9 /src
parent6f973faa912a5ac1ba643c6f5deb0c02baa0ba6d (diff)
downloademacs-1d4306a8a770cb73db3b39301ee41e15f9e3656f.tar.gz
emacs-1d4306a8a770cb73db3b39301ee41e15f9e3656f.zip
Implement Motif drop protocol
This is the second most widely implemented drag-and-drop protocol on X Windows, but seems to have some unsolvable problems (i.e. stuff will keep accumulating in the drag window as long the target lists keep changing.) The implementation is not yet complete and doesn't work with some programs. * lisp/select.el (xselect-convert-xm-special): New functions. (selection-converter-alist): Add new converters. * lisp/x-dnd.el (x-dnd-handle-motif): Ignore messages sent by the receiver. * src/xterm.c (xm_targets_table_byte_order): New enum; (SWAPCARD32, SWAPCARD16): New macros. (xm_targets_table_rec, xm_drop_start_message) (xm_drag_initiator_info, xm_drag_receiver_info): New structures. (XM_DRAG_SIDE_EFFECT, xm_read_targets_table_header) (xm_read_targets_table_rec, xm_find_targets_table_idx) (x_atoms_compare, xm_write_targets_table) (xm_write_drag_initiator_info, xm_get_drag_window) (xm_setup_dnd_targets, xm_send_drop_message) (xm_read_drag_receiver_info): New functions. (x_dnd_compute_toplevels): Correctly free some temp data. (x_dnd_get_window_proxy, x_dnd_get_window_proto) (x_set_frame_alpha): Likewise. (handle_one_xevent): If the window has no XDND proto but has motif drag receiver data, send a motif drop protocol request. (x_term_init): New atoms for Motif DND support. * src/xterm.h (struct x_display_info): Add new atoms.
Diffstat (limited to 'src')
-rw-r--r--src/xterm.c746
-rw-r--r--src/xterm.h4
2 files changed, 732 insertions, 18 deletions
diff --git a/src/xterm.c b/src/xterm.c
index a92c34396ca..bd5d756c8cc 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -861,6 +861,594 @@ struct x_client_list_window
861static struct x_client_list_window *x_dnd_toplevels = NULL; 861static struct x_client_list_window *x_dnd_toplevels = NULL;
862static bool x_dnd_use_toplevels; 862static bool x_dnd_use_toplevels;
863 863
864/* Motif drag-and-drop protocol support. */
865
866typedef enum xm_targets_table_byte_order
867 {
868 XM_TARGETS_TABLE_LSB = 'l',
869 XM_TARGETS_TABLE_MSB = 'B',
870#ifndef WORDS_BIGENDIAN
871 XM_TARGETS_TABLE_CUR = 'l',
872#else
873 XM_TARGETS_TABLE_CUR = 'B',
874#endif
875 } xm_targets_table_byte_order;
876
877#define SWAPCARD32(l) \
878 { \
879 struct { unsigned t : 32; } bit32; \
880 char n, *tp = (char *) &bit32; \
881 bit32.t = l; \
882 n = tp[0]; tp[0] = tp[3]; tp[3] = n; \
883 n = tp[1]; tp[1] = tp[2]; tp[2] = n; \
884 l = bit32.t; \
885 }
886
887#define SWAPCARD16(s) \
888 { \
889 struct { unsigned t : 16; } bit16; \
890 char n, *tp = (char *) &bit16; \
891 bit16.t = s; \
892 n = tp[0]; tp[0] = tp[1]; tp[1] = n; \
893 s = bit16.t; \
894 }
895
896typedef struct xm_targets_table_header
897{
898 /* BYTE */ uint8_t byte_order;
899 /* BYTE */ uint8_t protocol;
900
901 /* CARD16 */ uint16_t target_list_count;
902 /* CARD32 */ uint32_t total_data_size;
903} xm_targets_table_header;
904
905typedef struct xm_targets_table_rec
906{
907 /* CARD16 */ uint16_t n_targets;
908 /* CARD32 */ uint32_t targets[FLEXIBLE_ARRAY_MEMBER];
909} xm_targets_table_rec;
910
911typedef struct xm_drop_start_message
912{
913 /* BYTE */ uint8_t reason;
914 /* BYTE */ uint8_t byte_order;
915
916 /* CARD16 */ uint16_t side_effects;
917 /* CARD32 */ uint32_t timestamp;
918 /* CARD16 */ uint16_t x, y;
919 /* CARD32 */ uint32_t index_atom;
920 /* CARD32 */ uint32_t source_window;
921} xm_drop_start_message;
922
923typedef struct xm_drag_initiator_info
924{
925 /* BYTE */ uint8_t byteorder;
926 /* BYTE */ uint8_t protocol;
927
928 /* CARD16 */ uint16_t table_index;
929 /* CARD32 */ uint32_t selection;
930} xm_drag_initiator_info;
931
932typedef struct xm_drag_receiver_info
933{
934 /* BYTE */ uint8_t byteorder;
935 /* BYTE */ uint8_t protocol;
936
937 /* BYTE */ uint8_t protocol_style;
938 /* BYTE */ uint8_t unspecified0;
939 /* CARD32 */ uint32_t unspecified1;
940 /* CARD32 */ uint32_t unspecified2;
941 /* CARD32 */ uint32_t unspecified3;
942} xm_drag_receiver_info;
943
944#define XM_DRAG_SIDE_EFFECT(op, site, ops, act) \
945 ((op) | ((site) << 4) | ((ops) << 8) | ((act) << 16))
946
947/* Some of the macros below are temporarily unused. */
948
949/* #define XM_DRAG_SIDE_EFFECT_OPERATION(effect) ((effect) & 0xf) */
950/* #define XM_DRAG_SIDE_EFFECT_SITE_STATUS(effect) (((effect) & 0xf0) >> 4) */
951/* #define XM_DRAG_SIDE_EFFECT_OPERATIONS(effect) (((effect) & 0xf00) >> 8) */
952/* #define XM_DRAG_SIDE_EFFECT_DROP_ACTION(effect) (((effect) & 0xf000) >> 16) */
953
954#define XM_DRAG_NOOP 0
955#define XM_DRAG_MOVE (1L << 0)
956#define XM_DRAG_COPY (1L << 1)
957#define XM_DRAG_LINK (1L << 2)
958
959#define XM_DROP_ACTION_DROP 0
960#define XM_DROP_SITE_VALID 1
961
962#define XM_DRAG_REASON(originator, code) ((code) | ((originator) << 7))
963/* #define XM_DRAG_REASON_ORIGINATOR(reason) (((reason) & 0x80) ? 1 : 0) */
964/* #define XM_DRAG_REASON_CODE(reason) ((reason) & 0x7f) */
965
966#define XM_DRAG_REASON_DROP_START 5
967#define XM_DRAG_ORIGINATOR_INITIATOR 0
968/* #define XM_DRAG_ORIGINATOR_RECEIVER 1 */
969
970#define XM_DRAG_STYLE_NONE 0
971
972static uint8_t
973xm_side_effect_from_action (struct x_display_info *dpyinfo, Atom action)
974{
975 if (action == dpyinfo->Xatom_XdndActionCopy)
976 return XM_DRAG_COPY;
977 else if (action == dpyinfo->Xatom_XdndActionMove)
978 return XM_DRAG_MOVE;
979 else if (action == dpyinfo->Xatom_XdndActionLink)
980 return XM_DRAG_LINK;
981
982 return XM_DRAG_NOOP;
983}
984
985static int
986xm_read_targets_table_header (uint8_t *bytes, ptrdiff_t length,
987 xm_targets_table_header *header_return,
988 xm_targets_table_byte_order *byteorder_return)
989{
990 if (length < 8)
991 return -1;
992
993 header_return->byte_order = *byteorder_return = *(bytes++);
994 header_return->protocol = *(bytes++);
995
996 header_return->target_list_count = *(uint16_t *) bytes;
997 header_return->total_data_size = *(uint32_t *) (bytes + 2);
998
999 if (header_return->byte_order != XM_TARGETS_TABLE_CUR)
1000 {
1001 SWAPCARD16 (header_return->target_list_count);
1002 SWAPCARD32 (header_return->total_data_size);
1003 }
1004
1005 header_return->byte_order = XM_TARGETS_TABLE_CUR;
1006
1007 return 8;
1008}
1009
1010static xm_targets_table_rec *
1011xm_read_targets_table_rec (uint8_t *bytes, ptrdiff_t length,
1012 xm_targets_table_byte_order byteorder)
1013{
1014 uint16_t nitems, i;
1015 xm_targets_table_rec *rec;
1016
1017 if (length < 2)
1018 return NULL;
1019
1020 nitems = *(uint16_t *) bytes;
1021
1022 if (length < 2 + nitems * 4)
1023 return NULL;
1024
1025 if (byteorder != XM_TARGETS_TABLE_CUR)
1026 SWAPCARD16 (nitems);
1027
1028 rec = xmalloc (sizeof *rec + nitems * 4);
1029 rec->n_targets = nitems;
1030
1031 for (i = 0; i < nitems; ++i)
1032 {
1033 rec->targets[i] = ((uint32_t *) (bytes + 2))[i];
1034
1035 if (byteorder != XM_TARGETS_TABLE_CUR)
1036 SWAPCARD32 (rec->targets[i]);
1037 }
1038
1039 return rec;
1040}
1041
1042static int
1043xm_find_targets_table_idx (xm_targets_table_header *header,
1044 xm_targets_table_rec **recs,
1045 Atom *sorted_targets, int ntargets)
1046{
1047 int j;
1048 uint16_t i;
1049 uint32_t *targets;
1050
1051 targets = alloca (sizeof *targets * ntargets);
1052
1053 for (j = 0; j < ntargets; ++j)
1054 targets[j] = sorted_targets[j];
1055
1056 for (i = 0; i < header->target_list_count; ++i)
1057 {
1058 if (recs[i]->n_targets == ntargets
1059 && !memcmp (&recs[i]->targets, targets,
1060 sizeof *targets * ntargets))
1061 return i;
1062 }
1063
1064 return -1;
1065}
1066
1067static int
1068x_atoms_compare (const void *a, const void *b)
1069{
1070 return *(Atom *) a - *(Atom *) b;
1071}
1072
1073static void
1074xm_write_targets_table (Display *dpy, Window wdesc,
1075 Atom targets_table_atom,
1076 xm_targets_table_header *header,
1077 xm_targets_table_rec **recs)
1078{
1079 uint8_t *header_buffer, *ptr, *rec_buffer;
1080 ptrdiff_t rec_buffer_size;
1081 uint16_t i, j;
1082
1083 header_buffer = alloca (8);
1084 ptr = header_buffer;
1085
1086 *(header_buffer++) = header->byte_order;
1087 *(header_buffer++) = header->protocol;
1088 *((uint16_t *) header_buffer) = header->target_list_count;
1089 *((uint32_t *) (header_buffer + 2)) = header->total_data_size;
1090
1091 rec_buffer = xmalloc (600);
1092 rec_buffer_size = 600;
1093
1094 XGrabServer (dpy);
1095 XChangeProperty (dpy, wdesc, targets_table_atom,
1096 targets_table_atom, 8, PropModeReplace,
1097 (unsigned char *) ptr, 8);
1098
1099 for (i = 0; i < header->target_list_count; ++i)
1100 {
1101 if (rec_buffer_size < 2 + recs[i]->n_targets * 4)
1102 {
1103 rec_buffer_size = 2 + recs[i]->n_targets * 4;
1104 rec_buffer = xrealloc (rec_buffer, rec_buffer_size);
1105 }
1106
1107 *((uint16_t *) rec_buffer) = recs[i]->n_targets;
1108
1109 for (j = 0; j < recs[i]->n_targets; ++j)
1110 ((uint32_t *) (rec_buffer + 2))[j] = recs[i]->targets[j];
1111
1112 XChangeProperty (dpy, wdesc, targets_table_atom,
1113 targets_table_atom, 8, PropModeAppend,
1114 (unsigned char *) rec_buffer,
1115 2 + recs[i]->n_targets * 4);
1116 }
1117 XUngrabServer (dpy);
1118
1119 xfree (rec_buffer);
1120}
1121
1122static void
1123xm_write_drag_initiator_info (Display *dpy, Window wdesc,
1124 Atom prop_name, Atom type_name,
1125 xm_drag_initiator_info *info)
1126{
1127 uint8_t *buf;
1128
1129 buf = alloca (8);
1130 buf[0] = info->byteorder;
1131 buf[1] = info->protocol;
1132
1133 *((uint16_t *) (buf + 2)) = info->table_index;
1134 *((uint32_t *) (buf + 4)) = info->selection;
1135
1136 XChangeProperty (dpy, wdesc, prop_name, type_name, 8,
1137 PropModeReplace, (unsigned char *) buf, 8);
1138}
1139
1140static Window
1141xm_get_drag_window (struct x_display_info *dpyinfo)
1142{
1143 Atom actual_type;
1144 int rc, actual_format;
1145 unsigned long nitems, bytes_remaining;
1146 unsigned char *tmp_data = NULL;
1147 Window drag_window;
1148 XSetWindowAttributes attrs;
1149 XWindowAttributes wattrs;
1150 Display *temp_display;
1151
1152 drag_window = None;
1153 XGrabServer (dpyinfo->display);
1154 rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window,
1155 dpyinfo->Xatom_MOTIF_DRAG_WINDOW,
1156 0, 1, False, XA_WINDOW, &actual_type,
1157 &actual_format, &nitems, &bytes_remaining,
1158 &tmp_data) == Success;
1159
1160 if (rc)
1161 {
1162 if (actual_type == XA_WINDOW
1163 && actual_format == 32 && nitems == 1)
1164 {
1165 drag_window = *(Window *) tmp_data;
1166 x_catch_errors (dpyinfo->display);
1167 XGetWindowAttributes (dpyinfo->display,
1168 drag_window, &wattrs);
1169 rc = !x_had_errors_p (dpyinfo->display);
1170 x_uncatch_errors_after_check ();
1171
1172 if (!rc)
1173 drag_window = None;
1174 }
1175
1176 if (tmp_data)
1177 XFree (tmp_data);
1178 }
1179
1180 XUngrabServer (dpyinfo->display);
1181
1182 if (drag_window == None)
1183 {
1184 unrequest_sigio ();
1185 temp_display = XOpenDisplay (XDisplayString (dpyinfo->display));
1186 request_sigio ();
1187
1188 if (!temp_display)
1189 return None;
1190
1191 XSetCloseDownMode (temp_display, RetainPermanent);
1192
1193 XGrabServer (temp_display);
1194 attrs.override_redirect = True;
1195 drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display),
1196 -1, -1, 1, 1, 0, CopyFromParent, InputOnly,
1197 CopyFromParent, CWOverrideRedirect, &attrs);
1198 XChangeProperty (temp_display, DefaultRootWindow (temp_display),
1199 XInternAtom (temp_display,
1200 "_MOTIF_DRAG_WINDOW", False),
1201 XA_WINDOW, 32, PropModeReplace,
1202 (unsigned char *) &drag_window, 1);
1203 XUngrabServer (temp_display);
1204 XCloseDisplay (temp_display);
1205
1206 /* Make sure the drag window created is actually valid for the
1207 current display, and the XOpenDisplay above didn't
1208 accidentally connect to some other display. */
1209 x_catch_errors (dpyinfo->display);
1210 XGetWindowAttributes (dpyinfo->display,
1211 drag_window, &wattrs);
1212 rc = !x_had_errors_p (dpyinfo->display);
1213 x_uncatch_errors_after_check ();
1214
1215 /* We connected to the wrong display, so just give up. */
1216 if (!rc)
1217 drag_window = None;
1218 }
1219
1220 return drag_window;
1221}
1222
1223/* TODO: overflow checks when inserting targets. */
1224static int
1225xm_setup_dnd_targets (struct x_display_info *dpyinfo,
1226 Atom *targets, int ntargets)
1227{
1228 Window drag_window;
1229 Atom *targets_sorted, actual_type;
1230 unsigned char *tmp_data = NULL;
1231 unsigned long nitems, bytes_remaining;
1232 int rc, actual_format, idx;
1233 xm_targets_table_header header;
1234 xm_targets_table_rec **recs;
1235 xm_targets_table_byte_order byteorder;
1236 uint8_t *data;
1237 ptrdiff_t total_bytes, total_items, i;
1238
1239 drag_window = xm_get_drag_window (dpyinfo);
1240
1241 if (drag_window == None || ntargets > 64)
1242 return -1;
1243
1244 targets_sorted = xmalloc (sizeof *targets * ntargets);
1245 memcpy (targets_sorted, targets,
1246 sizeof *targets * ntargets);
1247 qsort (targets_sorted, ntargets,
1248 sizeof (Atom), x_atoms_compare);
1249
1250 XGrabServer (dpyinfo->display);
1251 rc = XGetWindowProperty (dpyinfo->display, drag_window,
1252 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
1253 /* Do larger values occur in practice? */
1254 0L, 20000L, False,
1255 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
1256 &actual_type, &actual_format, &nitems,
1257 &bytes_remaining, &tmp_data) == Success;
1258
1259 if (rc && tmp_data && !bytes_remaining
1260 && actual_type == dpyinfo->Xatom_MOTIF_DRAG_TARGETS
1261 && actual_format == 8)
1262 {
1263 data = (uint8_t *) tmp_data;
1264 if (xm_read_targets_table_header ((uint8_t *) tmp_data,
1265 nitems, &header,
1266 &byteorder) == 8)
1267 {
1268 data += 8;
1269 nitems -= 8;
1270 total_bytes = 0;
1271 total_items = 0;
1272
1273 /* The extra rec is used to store a new target list if a
1274 preexisting one doesn't already exist. */
1275 recs = xmalloc ((header.target_list_count + 1)
1276 * sizeof *recs);
1277
1278 while (total_items < header.target_list_count)
1279 {
1280 recs[total_items] = xm_read_targets_table_rec (data + total_bytes,
1281 nitems, byteorder);
1282
1283 if (!recs[total_items])
1284 break;
1285
1286 total_bytes += 2 + recs[total_items]->n_targets * 4;
1287 nitems -= 2 + recs[total_items]->n_targets * 4;
1288 total_items++;
1289 }
1290
1291 if (header.target_list_count != total_items
1292 || header.total_data_size != 8 + total_bytes)
1293 {
1294 for (i = 0; i < total_items; ++i)
1295 {
1296 if (recs[i])
1297 xfree (recs[i]);
1298 else
1299 break;
1300 }
1301
1302 xfree (recs);
1303
1304 rc = false;
1305 }
1306 }
1307 else
1308 rc = false;
1309 }
1310 else
1311 rc = false;
1312
1313 if (tmp_data)
1314 XFree (tmp_data);
1315
1316 /* Now rc means whether or not the target lists weren't updated and
1317 shouldn't be written to the drag window. */
1318
1319 if (!rc)
1320 {
1321 header.byte_order = XM_TARGETS_TABLE_CUR;
1322 header.protocol = 0;
1323 header.target_list_count = 1;
1324 header.total_data_size = 8 + 2 + ntargets * 4;
1325
1326 recs = xmalloc (sizeof *recs);
1327 recs[0] = xmalloc (sizeof **recs + ntargets * 4);
1328
1329 recs[0]->n_targets = ntargets;
1330
1331 for (i = 0; i < ntargets; ++i)
1332 recs[0]->targets[i] = targets_sorted[i];
1333
1334 idx = 0;
1335 }
1336 else
1337 {
1338 idx = xm_find_targets_table_idx (&header, recs,
1339 targets_sorted,
1340 ntargets);
1341
1342 if (idx == -1)
1343 {
1344 header.target_list_count++;
1345 header.total_data_size += 2 + ntargets * 4;
1346
1347 recs[header.target_list_count - 1] = xmalloc (sizeof **recs + ntargets * 4);
1348 recs[header.target_list_count - 1]->n_targets = ntargets;
1349
1350 for (i = 0; i < ntargets; ++i)
1351 recs[header.target_list_count - 1]->targets[i] = targets_sorted[i];
1352
1353 idx = header.target_list_count - 1;
1354 rc = false;
1355 }
1356 }
1357
1358 if (!rc)
1359 xm_write_targets_table (dpyinfo->display, drag_window,
1360 dpyinfo->Xatom_MOTIF_DRAG_TARGETS,
1361 &header, recs);
1362
1363 XUngrabServer (dpyinfo->display);
1364
1365 for (i = 0; i < header.target_list_count; ++i)
1366 xfree (recs[i]);
1367
1368 xfree (recs);
1369 xfree (targets_sorted);
1370
1371 return idx;
1372}
1373
1374static void
1375xm_send_drop_message (struct x_display_info *dpyinfo, Window source,
1376 Window target, xm_drop_start_message *dmsg)
1377{
1378 XEvent msg;
1379
1380 msg.xclient.type = ClientMessage;
1381 msg.xclient.message_type
1382 = dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE;
1383 msg.xclient.format = 8;
1384 msg.xclient.window = target;
1385 msg.xclient.data.b[0] = dmsg->reason;
1386 msg.xclient.data.b[1] = dmsg->byte_order;
1387 *((uint16_t *) &msg.xclient.data.b[2]) = dmsg->side_effects;
1388 *((uint32_t *) &msg.xclient.data.b[4]) = dmsg->timestamp;
1389 *((uint16_t *) &msg.xclient.data.b[8]) = dmsg->x;
1390 *((uint16_t *) &msg.xclient.data.b[10]) = dmsg->y;
1391 *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom;
1392 *((uint32_t *) &msg.xclient.data.b[16]) = dmsg->source_window;
1393
1394 x_catch_errors (dpyinfo->display);
1395 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
1396 x_uncatch_errors ();
1397}
1398
1399static int
1400xm_read_drag_receiver_info (struct x_display_info *dpyinfo,
1401 Window wdesc, xm_drag_receiver_info *rec)
1402{
1403 Atom actual_type;
1404 int rc, actual_format;
1405 unsigned long nitems, bytes_remaining;
1406 unsigned char *tmp_data = NULL;
1407 uint8_t *data;
1408
1409 x_catch_errors (dpyinfo->display);
1410 rc = XGetWindowProperty (dpyinfo->display, wdesc,
1411 dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
1412 0, LONG_MAX, False,
1413 dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
1414 &actual_type, &actual_format, &nitems,
1415 &bytes_remaining,
1416 &tmp_data) == Success;
1417
1418 if (x_had_errors_p (dpyinfo->display)
1419 || actual_format != 8 || nitems < 16 || !tmp_data
1420 || actual_type != dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO)
1421 rc = 0;
1422 x_uncatch_errors_after_check ();
1423
1424 if (rc)
1425 {
1426 data = (uint8_t *) tmp_data;
1427
1428 rec->byteorder = data[0];
1429 rec->protocol = data[1];
1430 rec->protocol_style = data[2];
1431 rec->unspecified0 = data[3];
1432 rec->unspecified1 = *(uint32_t *) &data[4];
1433 rec->unspecified2 = *(uint32_t *) &data[8];
1434 rec->unspecified3 = *(uint32_t *) &data[12];
1435
1436 if (rec->byteorder != XM_TARGETS_TABLE_CUR)
1437 {
1438 SWAPCARD32 (rec->unspecified1);
1439 SWAPCARD32 (rec->unspecified2);
1440 SWAPCARD32 (rec->unspecified3);
1441 }
1442
1443 rec->byteorder = XM_TARGETS_TABLE_CUR;
1444 }
1445
1446 if (tmp_data)
1447 XFree (tmp_data);
1448
1449 return !rc;
1450}
1451
864static void 1452static void
865x_dnd_free_toplevels (void) 1453x_dnd_free_toplevels (void)
866{ 1454{
@@ -1124,10 +1712,6 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
1124 tem->previous_event_mask = attrs.your_event_mask; 1712 tem->previous_event_mask = attrs.your_event_mask;
1125 tem->wm_state = wmstate[0]; 1713 tem->wm_state = wmstate[0];
1126 1714
1127#ifndef USE_XCB
1128 XFree (wmstate_data);
1129#endif
1130
1131#ifdef HAVE_XSHAPE 1715#ifdef HAVE_XSHAPE
1132#ifndef USE_XCB 1716#ifndef USE_XCB
1133 tem->border_width = attrs.border_width; 1717 tem->border_width = attrs.border_width;
@@ -1360,6 +1944,14 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
1360 if (geometry_reply) 1944 if (geometry_reply)
1361 free (geometry_reply); 1945 free (geometry_reply);
1362#endif 1946#endif
1947
1948#ifndef USE_XCB
1949 if (wmstate_data)
1950 {
1951 XFree (wmstate_data);
1952 wmstate_data = NULL;
1953 }
1954#endif
1363 } 1955 }
1364 1956
1365 return 0; 1957 return 0;
@@ -1715,7 +2307,7 @@ x_dnd_get_window_proxy (struct x_display_info *dpyinfo, Window wdesc)
1715{ 2307{
1716 int rc, actual_format; 2308 int rc, actual_format;
1717 unsigned long actual_size, bytes_remaining; 2309 unsigned long actual_size, bytes_remaining;
1718 unsigned char *tmp_data; 2310 unsigned char *tmp_data = NULL;
1719 XWindowAttributes attrs; 2311 XWindowAttributes attrs;
1720 Atom actual_type; 2312 Atom actual_type;
1721 Window proxy; 2313 Window proxy;
@@ -1731,12 +2323,12 @@ x_dnd_get_window_proxy (struct x_display_info *dpyinfo, Window wdesc)
1731 2323
1732 if (!x_had_errors_p (dpyinfo->display) 2324 if (!x_had_errors_p (dpyinfo->display)
1733 && rc == Success 2325 && rc == Success
2326 && tmp_data
1734 && actual_type == XA_WINDOW 2327 && actual_type == XA_WINDOW
1735 && actual_format == 32 2328 && actual_format == 32
1736 && actual_size == 1) 2329 && actual_size == 1)
1737 { 2330 {
1738 proxy = *(Window *) tmp_data; 2331 proxy = *(Window *) tmp_data;
1739 XFree (tmp_data);
1740 2332
1741 /* Verify the proxy window exists. */ 2333 /* Verify the proxy window exists. */
1742 XGetWindowAttributes (dpyinfo->display, proxy, &attrs); 2334 XGetWindowAttributes (dpyinfo->display, proxy, &attrs);
@@ -1744,6 +2336,9 @@ x_dnd_get_window_proxy (struct x_display_info *dpyinfo, Window wdesc)
1744 if (x_had_errors_p (dpyinfo->display)) 2336 if (x_had_errors_p (dpyinfo->display))
1745 proxy = None; 2337 proxy = None;
1746 } 2338 }
2339
2340 if (tmp_data)
2341 XFree (tmp_data);
1747 x_uncatch_errors_after_check (); 2342 x_uncatch_errors_after_check ();
1748 2343
1749 return proxy; 2344 return proxy;
@@ -1753,7 +2348,7 @@ static int
1753x_dnd_get_window_proto (struct x_display_info *dpyinfo, Window wdesc) 2348x_dnd_get_window_proto (struct x_display_info *dpyinfo, Window wdesc)
1754{ 2349{
1755 Atom actual, value; 2350 Atom actual, value;
1756 unsigned char *tmp_data; 2351 unsigned char *tmp_data = NULL;
1757 int rc, format; 2352 int rc, format;
1758 unsigned long n, left; 2353 unsigned long n, left;
1759 bool had_errors; 2354 bool had_errors;
@@ -1769,8 +2364,13 @@ x_dnd_get_window_proto (struct x_display_info *dpyinfo, Window wdesc)
1769 had_errors = x_had_errors_p (dpyinfo->display); 2364 had_errors = x_had_errors_p (dpyinfo->display);
1770 x_uncatch_errors_after_check (); 2365 x_uncatch_errors_after_check ();
1771 2366
1772 if (had_errors || rc != Success || actual != XA_ATOM || format != 32 || n < 1) 2367 if (had_errors || rc != Success || actual != XA_ATOM || format != 32 || n < 1
1773 return -1; 2368 || !tmp_data)
2369 {
2370 if (tmp_data)
2371 XFree (tmp_data);
2372 return -1;
2373 }
1774 2374
1775 value = (int) *(Atom *) tmp_data; 2375 value = (int) *(Atom *) tmp_data;
1776 XFree (tmp_data); 2376 XFree (tmp_data);
@@ -3545,7 +4145,7 @@ x_set_frame_alpha (struct frame *f)
3545 4145
3546 /* return unless necessary */ 4146 /* return unless necessary */
3547 { 4147 {
3548 unsigned char *data; 4148 unsigned char *data = NULL;
3549 Atom actual; 4149 Atom actual;
3550 int rc, format; 4150 int rc, format;
3551 unsigned long n, left; 4151 unsigned long n, left;
@@ -3555,16 +4155,19 @@ x_set_frame_alpha (struct frame *f)
3555 &actual, &format, &n, &left, 4155 &actual, &format, &n, &left,
3556 &data); 4156 &data);
3557 4157
3558 if (rc == Success && actual != None) 4158 if (rc == Success && actual != None && data)
3559 { 4159 {
3560 unsigned long value = *(unsigned long *)data; 4160 unsigned long value = *(unsigned long *) data;
3561 XFree (data);
3562 if (value == opac) 4161 if (value == opac)
3563 { 4162 {
3564 x_uncatch_errors (); 4163 x_uncatch_errors ();
4164 XFree (data);
3565 return; 4165 return;
3566 } 4166 }
3567 } 4167 }
4168
4169 if (data)
4170 XFree (data);
3568 } 4171 }
3569 4172
3570 XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity, 4173 XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity,
@@ -12144,12 +12747,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
12144 12747
12145 if (!x_had_errors_p (dpyinfo->display) && rc == Success && data 12748 if (!x_had_errors_p (dpyinfo->display) && rc == Success && data
12146 && nitems == 2 && actual_format == 32) 12749 && nitems == 2 && actual_format == 32)
12147 { 12750 tem->wm_state = ((unsigned long *) data)[0];
12148 tem->wm_state = ((unsigned long *) data)[0];
12149 XFree (data);
12150 }
12151 else 12751 else
12152 tem->wm_state = WithdrawnState; 12752 tem->wm_state = WithdrawnState;
12753
12754 if (data)
12755 XFree (data);
12153 x_uncatch_errors_after_check (); 12756 x_uncatch_errors_after_check ();
12154 } 12757 }
12155 12758
@@ -13569,6 +14172,56 @@ handle_one_xevent (struct x_display_info *dpyinfo,
13569 x_dnd_frame = NULL; 14172 x_dnd_frame = NULL;
13570 x_set_dnd_targets (NULL, 0); 14173 x_set_dnd_targets (NULL, 0);
13571 } 14174 }
14175 else if (x_dnd_last_seen_window != None)
14176 {
14177 xm_drag_receiver_info drag_receiver_info;
14178 xm_drag_initiator_info drag_initiator_info;
14179 xm_drop_start_message dmsg;
14180 int idx;
14181
14182 if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window,
14183 &drag_receiver_info)
14184 && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE)
14185 {
14186 idx = xm_setup_dnd_targets (dpyinfo, x_dnd_targets,
14187 x_dnd_n_targets);
14188
14189 if (idx != -1)
14190 {
14191 drag_initiator_info.byteorder = XM_TARGETS_TABLE_CUR;
14192 drag_initiator_info.protocol = 0;
14193 drag_initiator_info.table_index = idx;
14194 drag_initiator_info.selection = dpyinfo->Xatom_XdndSelection;
14195
14196 memset (&dmsg, 0, sizeof dmsg);
14197
14198 xm_write_drag_initiator_info (dpyinfo->display,
14199 FRAME_X_WINDOW (x_dnd_frame),
14200 dpyinfo->Xatom_MOTIF_DRAG_INITIATOR_INFO,
14201 dpyinfo->Xatom_MOTIF_DRAG_INITIATOR_INFO,
14202 &drag_initiator_info);
14203
14204 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
14205 XM_DRAG_REASON_DROP_START);
14206 dmsg.byte_order = XM_TARGETS_TABLE_CUR;
14207 dmsg.side_effects
14208 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
14209 x_dnd_wanted_action),
14210 XM_DROP_SITE_VALID,
14211 xm_side_effect_from_action (dpyinfo,
14212 x_dnd_wanted_action),
14213 XM_DROP_ACTION_DROP);
14214 dmsg.timestamp = event->xbutton.time;
14215 dmsg.x = event->xbutton.x_root;
14216 dmsg.y = event->xbutton.y_root;
14217 dmsg.index_atom = dpyinfo->Xatom_MOTIF_DRAG_INITIATOR_INFO;
14218 dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
14219
14220 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
14221 x_dnd_last_seen_window, &dmsg);
14222 }
14223 }
14224 }
13572 14225
13573 goto OTHER; 14226 goto OTHER;
13574 } 14227 }
@@ -14562,6 +15215,56 @@ handle_one_xevent (struct x_display_info *dpyinfo,
14562 x_dnd_selection_timestamp, 15215 x_dnd_selection_timestamp,
14563 x_dnd_last_protocol_version); 15216 x_dnd_last_protocol_version);
14564 } 15217 }
15218 else if (x_dnd_last_seen_window != None)
15219 {
15220 xm_drag_receiver_info drag_receiver_info;
15221 xm_drag_initiator_info drag_initiator_info;
15222 xm_drop_start_message dmsg;
15223 int idx;
15224
15225 if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window,
15226 &drag_receiver_info)
15227 && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE)
15228 {
15229 idx = xm_setup_dnd_targets (dpyinfo, x_dnd_targets,
15230 x_dnd_n_targets);
15231
15232 if (idx != -1)
15233 {
15234 drag_initiator_info.byteorder = XM_TARGETS_TABLE_CUR;
15235 drag_initiator_info.protocol = 0;
15236 drag_initiator_info.table_index = idx;
15237 drag_initiator_info.selection = dpyinfo->Xatom_XdndSelection;
15238
15239 memset (&dmsg, 0, sizeof dmsg);
15240
15241 xm_write_drag_initiator_info (dpyinfo->display,
15242 FRAME_X_WINDOW (x_dnd_frame),
15243 dpyinfo->Xatom_MOTIF_DRAG_INITIATOR_INFO,
15244 dpyinfo->Xatom_MOTIF_DRAG_INITIATOR_INFO,
15245 &drag_initiator_info);
15246
15247 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
15248 XM_DRAG_REASON_DROP_START);
15249 dmsg.byte_order = XM_TARGETS_TABLE_CUR;
15250 dmsg.side_effects
15251 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
15252 x_dnd_wanted_action),
15253 XM_DROP_SITE_VALID,
15254 xm_side_effect_from_action (dpyinfo,
15255 x_dnd_wanted_action),
15256 XM_DROP_ACTION_DROP);
15257 dmsg.timestamp = xev->time;
15258 dmsg.x = lrint (xev->root_x);
15259 dmsg.y = lrint (xev->root_y);
15260 dmsg.index_atom = dpyinfo->Xatom_MOTIF_DRAG_INITIATOR_INFO;
15261 dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame);
15262
15263 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame),
15264 x_dnd_last_seen_window, &dmsg);
15265 }
15266 }
15267 }
14565 15268
14566 x_dnd_last_protocol_version = -1; 15269 x_dnd_last_protocol_version = -1;
14567 x_dnd_last_seen_window = None; 15270 x_dnd_last_seen_window = None;
@@ -20420,6 +21123,15 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
20420 ATOM_REFS_INIT ("XdndLeave", Xatom_XdndLeave) 21123 ATOM_REFS_INIT ("XdndLeave", Xatom_XdndLeave)
20421 ATOM_REFS_INIT ("XdndDrop", Xatom_XdndDrop) 21124 ATOM_REFS_INIT ("XdndDrop", Xatom_XdndDrop)
20422 ATOM_REFS_INIT ("XdndFinished", Xatom_XdndFinished) 21125 ATOM_REFS_INIT ("XdndFinished", Xatom_XdndFinished)
21126 /* Motif drop protocol support. */
21127 ATOM_REFS_INIT ("_MOTIF_DRAG_WINDOW", Xatom_MOTIF_DRAG_WINDOW)
21128 ATOM_REFS_INIT ("_MOTIF_DRAG_TARGETS", Xatom_MOTIF_DRAG_TARGETS)
21129 ATOM_REFS_INIT ("_MOTIF_DRAG_AND_DROP_MESSAGE",
21130 Xatom_MOTIF_DRAG_AND_DROP_MESSAGE)
21131 ATOM_REFS_INIT ("_MOTIF_DRAG_INITIATOR_INFO",
21132 Xatom_MOTIF_DRAG_INITIATOR_INFO)
21133 ATOM_REFS_INIT ("_MOTIF_DRAG_RECEIVER_INFO",
21134 Xatom_MOTIF_DRAG_RECEIVER_INFO)
20423 }; 21135 };
20424 21136
20425 int i; 21137 int i;
diff --git a/src/xterm.h b/src/xterm.h
index 57b55ecf0db..eb9e25d3cdd 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -433,7 +433,9 @@ struct x_display_info
433 /* Atom used to determine whether or not the screen is composited. */ 433 /* Atom used to determine whether or not the screen is composited. */
434 Atom Xatom_NET_WM_CM_Sn; 434 Atom Xatom_NET_WM_CM_Sn;
435 435
436 Atom Xatom_MOTIF_WM_HINTS; 436 Atom Xatom_MOTIF_WM_HINTS, Xatom_MOTIF_DRAG_WINDOW,
437 Xatom_MOTIF_DRAG_TARGETS, Xatom_MOTIF_DRAG_AND_DROP_MESSAGE,
438 Xatom_MOTIF_DRAG_INITIATOR_INFO, Xatom_MOTIF_DRAG_RECEIVER_INFO;
437 439
438 /* The frame (if any) which has the X window that has keyboard focus. 440 /* The frame (if any) which has the X window that has keyboard focus.
439 Zero if none. This is examined by Ffocus_frame in xfns.c. Note 441 Zero if none. This is examined by Ffocus_frame in xfns.c. Note