From: Po Lu Date: Wed, 6 Apr 2022 05:54:31 +0000 (+0000) Subject: Improve safety of haiku-drag-message X-Git-Tag: emacs-29.0.90~1931^2~747 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=78ecd67888566167fb4c881d8350f611fa039649;p=emacs.git Improve safety of haiku-drag-message * lisp/term/haiku-win.el (haiku-drag-and-drop): Ignore placeholder message. * src/frame.c (delete_frame): Prevent deleting drop source frame on Haiku. * src/haiku_support.cc (RELEASE_NOW, CANCEL_DROP): New message types. (class EmacsView, MessageReceived): Handle new message types. (be_drag_message): Drag CANCEL_DROP message on quit; also send RELEASE_NOW to view if quitting. * src/haikuselect.c (syms_of_haikuselect) (haiku_unwind_drag_message): Clear new frame variable. (Fhaiku_drag_message): Set new frame variable. * src/haikuterm.h: Update prototypes. --- diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 6f8f9ac5196..955947fe6a2 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -264,8 +264,11 @@ VALUE will be encoded as UTF-8 and stored under the type (if (multibyte-string-p text) text (decode-coding-string text 'undecided)))))) - (t (message "Don't know how to drop any of: %s" - (mapcar #'car string))))))) + ((not (eq (cdr (assq 'type string)) + 3003)) ; Type of the placeholder message Emacs uses + ; to cancel a drop on C-g. + (message "Don't know how to drop any of: %s" + (mapcar #'car string))))))) (define-key special-event-map [drag-n-drop] 'haiku-drag-and-drop) diff --git a/src/frame.c b/src/frame.c index 05b22ac72ba..93028aa8958 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1991,6 +1991,10 @@ delete_frame (Lisp_Object frame, Lisp_Object force) else if (x_dnd_in_progress && f == x_dnd_frame) error ("Attempt to delete the drop source frame"); #endif +#ifdef HAVE_HAIKU + else if (f == haiku_dnd_frame) + error ("Attempt to delete the drop source frame"); +#endif XSETFRAME (frame, f); diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 830255d3f07..cb38a572f7c 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -81,8 +81,13 @@ along with GNU Emacs. If not, see . */ #include "haiku_support.h" -#define SCROLL_BAR_UPDATE 3000 -#define WAIT_FOR_RELEASE 3001 +enum + { + SCROLL_BAR_UPDATE = 3000, + WAIT_FOR_RELEASE = 3001, + RELEASE_NOW = 3002, + CANCEL_DROP = 3003, + }; static color_space dpy_color_space = B_NO_COLOR_SPACE; static key_map *key_map = NULL; @@ -1272,7 +1277,10 @@ public: ~EmacsView () { if (wait_for_release_message) - gui_abort ("Wait for release message still exists"); + { + wait_for_release_message->SendReply (wait_for_release_message); + delete wait_for_release_message; + } TearDownDoubleBuffering (); @@ -1307,6 +1315,14 @@ public: else wait_for_release_message = looper->DetachCurrentMessage (); } + else if (msg->what == RELEASE_NOW) + { + if (wait_for_release_message) + wait_for_release_message->SendReply (msg); + + delete wait_for_release_message; + wait_for_release_message = NULL; + } else BView::MessageReceived (msg); } @@ -4087,6 +4103,7 @@ be_drag_message (void *view, void *message, bool allow_same_view, BMessage *msg = (BMessage *) message; BMessage wait_for_release; BMessenger messenger (vw); + BMessage cancel_message (CANCEL_DROP); struct object_wait_info infos[2]; ssize_t stat; @@ -4142,6 +4159,16 @@ be_drag_message (void *view, void *message, bool allow_same_view, if (should_quit_function ()) { + /* Do the best we can to prevent something from being + dropped, since Haiku doesn't provide a way to actually + cancel drag-and-drop. */ + if (vw->LockLooper ()) + { + vw->DragMessage (&cancel_message, BRect (0, 0, 0, 0)); + vw->UnlockLooper (); + } + + messenger.SendMessage (CANCEL_DROP); drag_and_drop_in_progress = false; return true; } diff --git a/src/haikuselect.c b/src/haikuselect.c index c3053688f5a..a186acc66ff 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -27,6 +27,12 @@ along with GNU Emacs. If not, see . */ #include +/* The frame that is currently the source of a drag-and-drop + operation, or NULL if none is in progress. The reason for this + variable is to prevent it from being deleted, which really breaks + the nested event loop inside be_drag_message. */ +struct frame *haiku_dnd_frame; + static void haiku_lisp_to_message (Lisp_Object, void *); DEFUN ("haiku-selection-data", Fhaiku_selection_data, Shaiku_selection_data, @@ -726,6 +732,7 @@ haiku_should_quit_drag (void) static void haiku_unwind_drag_message (void *message) { + haiku_dnd_frame = NULL; BMessage_delete (message); } @@ -774,6 +781,7 @@ ignored if it is dropped on top of FRAME. */) if (!FRAME_VISIBLE_P (f)) error ("Frame is invisible"); + haiku_dnd_frame = f; be_message = be_create_simple_message (); record_unwind_protect_ptr (haiku_unwind_drag_message, be_message); @@ -852,4 +860,6 @@ used to retrieve the current position of the mouse. */); defsubr (&Shaiku_selection_put); defsubr (&Shaiku_selection_owner_p); defsubr (&Shaiku_drag_message); + + haiku_dnd_frame = NULL; } diff --git a/src/haikuterm.h b/src/haikuterm.h index 8f311b2ab12..586df285751 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h @@ -192,6 +192,7 @@ extern struct haiku_display_info *x_display_list; extern struct font_driver const haikufont_driver; extern Lisp_Object tip_frame; +extern struct frame *haiku_dnd_frame; struct scroll_bar {