aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-03-20 15:00:36 +0800
committerPo Lu2022-03-20 15:00:36 +0800
commit9b34005c32462a3e0e8a201e3b0d52a67a84d7bd (patch)
treedffd490c0f8d9d2394776880736dd54cadbf98f4 /src
parent34ac8088b002e59e943471c4b39c368aebaca45c (diff)
downloademacs-9b34005c32462a3e0e8a201e3b0d52a67a84d7bd.tar.gz
emacs-9b34005c32462a3e0e8a201e3b0d52a67a84d7bd.zip
Improve compliance with version 5 of the XDND specification
* src/xterm.c (x_dnd_cleanup_drag_and_drop): New function. (x_dnd_begin_drag_and_drop): Handle selection request events immediately. (handle_one_xevent): Wait for XdndFinished events and return the action chosen there.
Diffstat (limited to 'src')
-rw-r--r--src/xterm.c113
1 files changed, 106 insertions, 7 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 01840569fef..98888414d53 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -788,6 +788,9 @@ static void x_scroll_bar_end_update (struct x_display_info *, struct scroll_bar
788#endif 788#endif
789 789
790static bool x_dnd_in_progress; 790static bool x_dnd_in_progress;
791static bool x_dnd_waiting_for_finish;
792static Window x_dnd_pending_finish_target;
793static int x_dnd_waiting_for_finish_proto;
791 794
792/* Whether or not to return a frame from `x_dnd_begin_drag_and_drop'. 795/* Whether or not to return a frame from `x_dnd_begin_drag_and_drop'.
793 796
@@ -809,6 +812,9 @@ static Atom x_dnd_wanted_action;
809static Atom *x_dnd_targets = NULL; 812static Atom *x_dnd_targets = NULL;
810static int x_dnd_n_targets; 813static int x_dnd_n_targets;
811static struct frame *x_dnd_frame; 814static struct frame *x_dnd_frame;
815static XWindowAttributes x_dnd_old_window_attrs;
816static XIC x_dnd_old_ic;
817static bool x_dnd_unwind_flag;
812 818
813#define X_DND_SUPPORTED_VERSION 5 819#define X_DND_SUPPORTED_VERSION 5
814 820
@@ -1145,6 +1151,47 @@ x_set_dnd_targets (Atom *targets, int ntargets)
1145 x_dnd_n_targets = ntargets; 1151 x_dnd_n_targets = ntargets;
1146} 1152}
1147 1153
1154static void
1155x_dnd_cleanup_drag_and_drop (void *frame)
1156{
1157 struct frame *f = frame;
1158
1159 if (!x_dnd_unwind_flag)
1160 return;
1161
1162 if (x_dnd_in_progress)
1163 {
1164 eassert (x_dnd_frame);
1165
1166 block_input ();
1167 if (x_dnd_last_seen_window != None
1168 && x_dnd_last_protocol_version != -1)
1169 x_dnd_send_leave (x_dnd_frame,
1170 x_dnd_last_seen_window);
1171 unblock_input ();
1172
1173 x_dnd_in_progress = false;
1174 x_set_dnd_targets (NULL, 0);
1175 }
1176
1177 FRAME_DISPLAY_INFO (f)->grabbed = 0;
1178#ifdef USE_GTK
1179 current_hold_quit = NULL;
1180#endif
1181#ifdef HAVE_X_I18N
1182 FRAME_XIC (f) = x_dnd_old_ic;
1183#endif
1184
1185 block_input ();
1186 /* Restore the old event mask. */
1187 XSelectInput (FRAME_X_DISPLAY (f),
1188 FRAME_DISPLAY_INFO (f)->root_window,
1189 x_dnd_old_window_attrs.your_event_mask);
1190 unblock_input ();
1191
1192 x_dnd_frame = NULL;
1193}
1194
1148Lisp_Object 1195Lisp_Object
1149x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, 1196x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
1150 bool return_frame_p) 1197 bool return_frame_p)
@@ -1161,6 +1208,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
1161 struct input_event hold_quit; 1208 struct input_event hold_quit;
1162 char *atom_name; 1209 char *atom_name;
1163 Lisp_Object action, ltimestamp; 1210 Lisp_Object action, ltimestamp;
1211 specpdl_ref ref;
1164 1212
1165 if (!FRAME_VISIBLE_P (f)) 1213 if (!FRAME_VISIBLE_P (f))
1166 error ("Frame is invisible"); 1214 error ("Frame is invisible");
@@ -1187,6 +1235,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
1187 x_dnd_action = None; 1235 x_dnd_action = None;
1188 x_dnd_wanted_action = xaction; 1236 x_dnd_wanted_action = xaction;
1189 x_dnd_return_frame = 0; 1237 x_dnd_return_frame = 0;
1238 x_dnd_waiting_for_finish = false;
1190 1239
1191 if (return_frame_p) 1240 if (return_frame_p)
1192 x_dnd_return_frame = 1; 1241 x_dnd_return_frame = 1;
@@ -1215,7 +1264,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
1215 Otherwise, the ibus XIM server gets very confused. */ 1264 Otherwise, the ibus XIM server gets very confused. */
1216 FRAME_XIC (f) = NULL; 1265 FRAME_XIC (f) = NULL;
1217#endif 1266#endif
1218 while (x_dnd_in_progress) 1267 while (x_dnd_in_progress || x_dnd_waiting_for_finish)
1219 { 1268 {
1220 hold_quit.kind = NO_EVENT; 1269 hold_quit.kind = NO_EVENT;
1221#ifdef USE_GTK 1270#ifdef USE_GTK
@@ -1234,6 +1283,20 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
1234 1283
1235 if (hold_quit.kind != NO_EVENT) 1284 if (hold_quit.kind != NO_EVENT)
1236 { 1285 {
1286 if (hold_quit.kind == SELECTION_REQUEST_EVENT)
1287 {
1288 x_dnd_old_ic = ic;
1289 x_dnd_old_window_attrs = root_window_attrs;
1290 x_dnd_unwind_flag = true;
1291
1292 ref = SPECPDL_INDEX ();
1293 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
1294 x_handle_selection_event ((struct selection_input_event *) &hold_quit);
1295 x_dnd_unwind_flag = false;
1296 unbind_to (ref, Qnil);
1297 continue;
1298 }
1299
1237 if (x_dnd_in_progress) 1300 if (x_dnd_in_progress)
1238 { 1301 {
1239 if (x_dnd_last_seen_window != None 1302 if (x_dnd_last_seen_window != None
@@ -10771,6 +10834,20 @@ handle_one_xevent (struct x_display_info *dpyinfo,
10771 } 10834 }
10772 } 10835 }
10773 10836
10837 if (event->xclient.message_type == dpyinfo->Xatom_XdndFinished
10838 && x_dnd_waiting_for_finish
10839 && event->xclient.data.l[0] == x_dnd_pending_finish_target)
10840 {
10841 x_dnd_waiting_for_finish = false;
10842
10843 if (x_dnd_waiting_for_finish_proto >= 5)
10844 x_dnd_wanted_action = event->xclient.data.l[2];
10845
10846 if (x_dnd_waiting_for_finish_proto >= 5
10847 && !(event->xclient.data.l[1] & 1))
10848 x_dnd_wanted_action = None;
10849 }
10850
10774 if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols 10851 if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols
10775 && event->xclient.format == 32) 10852 && event->xclient.format == 32)
10776 { 10853 {
@@ -11055,6 +11132,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
11055 SELECTION_EVENT_TARGET (&inev.sie) = eventp->target; 11132 SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
11056 SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property; 11133 SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
11057 SELECTION_EVENT_TIME (&inev.sie) = eventp->time; 11134 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
11135
11136 /* If drag-and-drop is in progress, handle SelectionRequest
11137 events immediately, by setting hold_quit to the input
11138 event. */
11139
11140 if (x_dnd_in_progress || x_dnd_waiting_for_finish)
11141 {
11142 *hold_quit = inev.ie;
11143 EVENT_INIT (inev.ie);
11144 }
11058 } 11145 }
11059 break; 11146 break;
11060 11147
@@ -12341,9 +12428,15 @@ handle_one_xevent (struct x_display_info *dpyinfo,
12341 12428
12342 if (x_dnd_last_seen_window != None 12429 if (x_dnd_last_seen_window != None
12343 && x_dnd_last_protocol_version != -1) 12430 && x_dnd_last_protocol_version != -1)
12344 x_dnd_send_drop (x_dnd_frame, x_dnd_last_seen_window, 12431 {
12345 x_dnd_selection_timestamp, 12432 x_dnd_waiting_for_finish = true;
12346 x_dnd_last_protocol_version); 12433 x_dnd_pending_finish_target = x_dnd_last_seen_window;
12434 x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version;
12435
12436 x_dnd_send_drop (x_dnd_frame, x_dnd_last_seen_window,
12437 x_dnd_selection_timestamp,
12438 x_dnd_last_protocol_version);
12439 }
12347 12440
12348 x_dnd_last_protocol_version = -1; 12441 x_dnd_last_protocol_version = -1;
12349 x_dnd_last_seen_window = None; 12442 x_dnd_last_seen_window = None;
@@ -13320,9 +13413,15 @@ handle_one_xevent (struct x_display_info *dpyinfo,
13320 13413
13321 if (x_dnd_last_seen_window != None 13414 if (x_dnd_last_seen_window != None
13322 && x_dnd_last_protocol_version != -1) 13415 && x_dnd_last_protocol_version != -1)
13323 x_dnd_send_drop (x_dnd_frame, x_dnd_last_seen_window, 13416 {
13324 x_dnd_selection_timestamp, 13417 x_dnd_waiting_for_finish = true;
13325 x_dnd_last_protocol_version); 13418 x_dnd_pending_finish_target = x_dnd_last_seen_window;
13419 x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version;
13420
13421 x_dnd_send_drop (x_dnd_frame, x_dnd_last_seen_window,
13422 x_dnd_selection_timestamp,
13423 x_dnd_last_protocol_version);
13424 }
13326 13425
13327 x_dnd_last_protocol_version = -1; 13426 x_dnd_last_protocol_version = -1;
13328 x_dnd_last_seen_window = None; 13427 x_dnd_last_seen_window = None;