]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix frame destruction issues and misuse of x_get_atom_name
authorPo Lu <luangruo@yahoo.com>
Sat, 28 May 2022 01:37:29 +0000 (09:37 +0800)
committerPo Lu <luangruo@yahoo.com>
Sat, 28 May 2022 01:37:29 +0000 (09:37 +0800)
* 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.

src/frame.c
src/xselect.c
src/xterm.c
src/xterm.h

index 252dc591bfa364ffa0c7224cecac0803494aedf8..ea4c904e20a6a9f00a6071e9a57732cf27792aab 100644 (file)
@@ -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
index 3f35842daa08f9893171e91efb22b921ed11de26..bfd081b1e28ccecb7c15b43372ffa9c24de2c608 100644 (file)
@@ -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;
 }
index 756f0308111cf589f28aa9f8a861abcdf7814fc7..94c996a11dc13dfe18f2701ec1d689d40872695a 100644 (file)
@@ -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)
        {
index 283d4fa9b115b566feea2c88def661003a45095d..6c798ea246d0476a514031490714ec1fb59eb8ff 100644 (file)
@@ -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