summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-05-28 09:37:29 +0800
committerPo Lu <luangruo@yahoo.com>2022-05-28 09:37:29 +0800
commitac13957b86ad699a76a0b248063551f971c4cef9 (patch)
treec8c92ca5f92802e7807d7aaa58ea112b836e39cc /src
parentb2c8e8a299dadce7dc1bae2adf73ee9303856bb6 (diff)
downloademacs-ac13957b86ad699a76a0b248063551f971c4cef9.tar.gz
Fix frame destruction issues and misuse of x_get_atom_name
* src/frame.c (delete_frame): Prevent deleting the dnd frame while waiting for finish as well. * src/xselect.c (Fx_get_atom_name): Clean up code and fix uninitialized use of need_sync. * src/xterm.c (x_dnd_send_unsupported_drop, x_dnd_send_drop) (handle_one_xevent): Clean up usage of x_get_atom_name. (x_get_atom_name): Accept NULL for need_sync. * src/xterm.h: Update declarations.
Diffstat (limited to 'src')
-rw-r--r--src/frame.c3
-rw-r--r--src/xselect.c11
-rw-r--r--src/xterm.c29
-rw-r--r--src/xterm.h2
4 files changed, 34 insertions, 11 deletions
diff --git a/src/frame.c b/src/frame.c
index 252dc591bfa..ea4c904e20a 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1995,7 +1995,8 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
error ("Attempt to delete the only frame");
}
#ifdef HAVE_X_WINDOWS
- else if (x_dnd_in_progress && f == x_dnd_frame)
+ else if ((x_dnd_in_progress && f == x_dnd_frame)
+ || (x_dnd_waiting_for_finish && f == x_dnd_finish_frame))
error ("Attempt to delete the drop source frame");
#endif
#ifdef HAVE_HAIKU
diff --git a/src/xselect.c b/src/xselect.c
index 3f35842daa0..bfd081b1e28 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -2458,24 +2458,25 @@ If the value is 0 or the atom is not known, return the empty string. */)
struct x_display_info *dpyinfo;
Atom atom;
bool had_errors_p, need_sync;
+ char *name;
+ Lisp_Object ret;
dpyinfo = FRAME_DISPLAY_INFO (f);
-
CONS_TO_INTEGER (value, Atom, atom);
- block_input ();
x_catch_errors (dpy);
- char *name = atom ? x_get_atom_name (dpyinfo, atom, &need_sync) : NULL;
+ name = x_get_atom_name (dpyinfo, atom, &need_sync);
had_errors_p = need_sync && x_had_errors_p (dpy);
x_uncatch_errors_after_check ();
- Lisp_Object ret = empty_unibyte_string;
+
+ ret = empty_unibyte_string;
+
if (name)
{
if (!had_errors_p)
ret = build_string (name);
xfree (name);
}
- unblock_input ();
return ret;
}
diff --git a/src/xterm.c b/src/xterm.c
index 756f0308111..94c996a11dc 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1011,11 +1011,16 @@ unsigned x_dnd_unsupported_event_level;
/* The frame where the drag-and-drop operation originated. */
struct frame *x_dnd_frame;
+/* That frame, but set when x_dnd_waiting_for_finish is true. Used to
+ prevent the frame from being deleted inside selection handlers and
+ other callbacks. */
+struct frame *x_dnd_finish_frame;
+
/* Flag that indicates if a drag-and-drop operation is no longer in
progress, but the nested event loop should continue to run, because
handle_one_xevent is waiting for the drop target to return some
important information. */
-static bool x_dnd_waiting_for_finish;
+bool x_dnd_waiting_for_finish;
/* The display the drop target that is supposed to send information is
on. */
@@ -3277,7 +3282,7 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo
}
name = x_get_atom_name (dpyinfo, x_dnd_wanted_action,
- false);
+ NULL);
if (name)
{
@@ -3842,7 +3847,7 @@ x_dnd_send_drop (struct frame *f, Window target, Time timestamp,
lval = Qnil;
atom_names = alloca (x_dnd_n_targets * sizeof *atom_names);
- name = x_get_atom_name (dpyinfo, x_dnd_wanted_action, false);
+ name = x_get_atom_name (dpyinfo, x_dnd_wanted_action, NULL);
if (!XGetAtomNames (dpyinfo->display, x_dnd_targets,
x_dnd_n_targets, atom_names))
@@ -17226,6 +17231,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
x_dnd_end_window = x_dnd_last_seen_window;
x_dnd_in_progress = false;
+ x_dnd_finish_frame = x_dnd_frame;
if (x_dnd_last_seen_window != None
&& x_dnd_last_protocol_version != -1)
@@ -18531,6 +18537,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_dnd_end_window = x_dnd_last_seen_window;
x_dnd_in_progress = false;
+ /* This doesn't have to be marked since it
+ is only accessed if
+ x_dnd_waiting_for_finish is true, which
+ is only possible inside the DND event
+ loop where that frame is on the
+ stack. */
+ x_dnd_finish_frame = x_dnd_frame;
+
if (x_dnd_last_seen_window != None
&& x_dnd_last_protocol_version != -1)
{
@@ -23830,7 +23844,10 @@ x_get_atom_name (struct x_display_info *dpyinfo, Atom atom,
dpyinfo_pointer = (char *) dpyinfo;
value = NULL;
- *need_sync = false;
+
+ if (need_sync)
+ *need_sync = false;
+
buffer = alloca (45 + INT_STRLEN_BOUND (int));
switch (atom)
@@ -23878,7 +23895,9 @@ x_get_atom_name (struct x_display_info *dpyinfo, Atom atom,
}
name = XGetAtomName (dpyinfo->display, atom);
- *need_sync = true;
+
+ if (need_sync)
+ *need_sync = true;
if (name)
{
diff --git a/src/xterm.h b/src/xterm.h
index 283d4fa9b11..6c798ea246d 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1603,7 +1603,9 @@ extern struct input_event xg_pending_quit_event;
#endif
extern bool x_dnd_in_progress;
+extern bool x_dnd_waiting_for_finish;
extern struct frame *x_dnd_frame;
+extern struct frame *x_dnd_finish_frame;
extern unsigned x_dnd_unsupported_event_level;
#ifdef HAVE_XINPUT2