diff options
| author | Po Lu | 2022-03-31 17:21:37 +0800 |
|---|---|---|
| committer | Po Lu | 2022-03-31 17:21:37 +0800 |
| commit | 1d4306a8a770cb73db3b39301ee41e15f9e3656f (patch) | |
| tree | b40831da1ca6a8aaf016e2d4e1c556d4ff22dfc9 /src | |
| parent | 6f973faa912a5ac1ba643c6f5deb0c02baa0ba6d (diff) | |
| download | emacs-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.c | 746 | ||||
| -rw-r--r-- | src/xterm.h | 4 |
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 | |||
| 861 | static struct x_client_list_window *x_dnd_toplevels = NULL; | 861 | static struct x_client_list_window *x_dnd_toplevels = NULL; |
| 862 | static bool x_dnd_use_toplevels; | 862 | static bool x_dnd_use_toplevels; |
| 863 | 863 | ||
| 864 | /* Motif drag-and-drop protocol support. */ | ||
| 865 | |||
| 866 | typedef 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 | |||
| 896 | typedef 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 | |||
| 905 | typedef 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 | |||
| 911 | typedef 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 | |||
| 923 | typedef 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 | |||
| 932 | typedef 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 | |||
| 972 | static uint8_t | ||
| 973 | xm_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 | |||
| 985 | static int | ||
| 986 | xm_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 | |||
| 1010 | static xm_targets_table_rec * | ||
| 1011 | xm_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 | |||
| 1042 | static int | ||
| 1043 | xm_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 | |||
| 1067 | static int | ||
| 1068 | x_atoms_compare (const void *a, const void *b) | ||
| 1069 | { | ||
| 1070 | return *(Atom *) a - *(Atom *) b; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | static void | ||
| 1074 | xm_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 | |||
| 1122 | static void | ||
| 1123 | xm_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 | |||
| 1140 | static Window | ||
| 1141 | xm_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. */ | ||
| 1224 | static int | ||
| 1225 | xm_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 | |||
| 1374 | static void | ||
| 1375 | xm_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 | |||
| 1399 | static int | ||
| 1400 | xm_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 | |||
| 864 | static void | 1452 | static void |
| 865 | x_dnd_free_toplevels (void) | 1453 | x_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 | |||
| 1753 | x_dnd_get_window_proto (struct x_display_info *dpyinfo, Window wdesc) | 2348 | x_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 |