From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: martin rudalics Newsgroups: gmane.emacs.bugs Subject: bug#33498: 26.1; Unable to delete minibuffer-only+child frames Date: Tue, 27 Nov 2018 11:14:35 +0100 Message-ID: <5BFD190B.8090800@gmx.at> References: <8736rpfklv.fsf@hochschule-trier.de> <5BFADE8C.9040500@gmx.at> <87h8g5ggft.fsf@hochschule-trier.de> <5BFAF08C.6080500@gmx.at> <87d0qtgdfx.fsf@hochschule-trier.de> <5BFBBD5A.4060002@gmx.at> <871s77hdgm.fsf@hochschule-trier.de> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Trace: blaine.gmane.org 1543313585 29302 195.159.176.226 (27 Nov 2018 10:13:05 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Tue, 27 Nov 2018 10:13:05 +0000 (UTC) Cc: 33498@debbugs.gnu.org To: Andreas Politz Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Tue Nov 27 11:13:01 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gRaMX-0007TS-Do for geb-bug-gnu-emacs@m.gmane.org; Tue, 27 Nov 2018 11:13:01 +0100 Original-Received: from localhost ([::1]:41225 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gRaOe-0003cC-0W for geb-bug-gnu-emacs@m.gmane.org; Tue, 27 Nov 2018 05:15:12 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:34554) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gRaOY-0003br-6J for bug-gnu-emacs@gnu.org; Tue, 27 Nov 2018 05:15:07 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gRaOV-0002IV-0N for bug-gnu-emacs@gnu.org; Tue, 27 Nov 2018 05:15:06 -0500 Original-Received: from debbugs.gnu.org ([208.118.235.43]:46201) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gRaOU-0002IJ-T0 for bug-gnu-emacs@gnu.org; Tue, 27 Nov 2018 05:15:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1gRaOU-00042P-Jh for bug-gnu-emacs@gnu.org; Tue, 27 Nov 2018 05:15:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: martin rudalics Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 27 Nov 2018 10:15:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 33498 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 33498-submit@debbugs.gnu.org id=B33498.154331369215491 (code B ref 33498); Tue, 27 Nov 2018 10:15:02 +0000 Original-Received: (at 33498) by debbugs.gnu.org; 27 Nov 2018 10:14:52 +0000 Original-Received: from localhost ([127.0.0.1]:50459 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gRaOJ-00041m-UP for submit@debbugs.gnu.org; Tue, 27 Nov 2018 05:14:52 -0500 Original-Received: from mout.gmx.net ([212.227.15.19]:52577) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gRaOH-00041W-3u for 33498@debbugs.gnu.org; Tue, 27 Nov 2018 05:14:50 -0500 Original-Received: from [192.168.1.101] ([46.125.250.122]) by mail.gmx.com (mrgmx002 [212.227.17.190]) with ESMTPSA (Nemesis) id 0Ld0jY-1fjlGD1xyq-00iBV3; Tue, 27 Nov 2018 11:14:41 +0100 In-Reply-To: <871s77hdgm.fsf@hochschule-trier.de> X-Provags-ID: V03:K1:ewTRm3JWVdJULezro8Fvs+Z+zCmZ/J3lJ0Q8mf9s9VvZgA5mTvr QbtSTEPvnwm0G4swglFZIwjPqVhJEbYabbfoVbbI4Cm/vUcuTlHv1bafcPZvSHtJqtt9w7F ok6+DoXEtdpzt0iqe3rIWwBDzXxJUAf3SvjR4wLZUA7dgHQRIGLQ12+nNkDezXSoAiicfYI xsdTIeoSSDs+tmPk7VY+Q== X-UI-Out-Filterresults: notjunk:1;V03:K0:OhlZAPDCZbs=:55YI288dTzWqqa7YhBoo7Q 953YtcQa6wlZtgeKGdVwN4g+xHyuXkFx4PekSs9g8ghGfXKJhhp+BdshlgUNQDbEtaHyKv8SY XMmI4OlUbYDW1KkMjxqXsPYbbVumumH52kjVk+MHKjXiFXzxcHDVqlVxRfTrhBqZBN0dms/h+ fNYsxuCLszl8scgvRqvKk2SyOc++2qk/WyFNQK1djEt6TkJ3sj8rCRd3rhEDlaOqRam3+hWxy iUXxJCr6RT2KxsRPA8XBQ9zDFad14VKwM+mzUCdf3vmJ6RBudPMs18seI/GxsRJffhcfhuWR2 vPkNPmRe6ghLAXMrk7qlLAjlXxcjakTcEtBaCFLMfhSbrO+xsQu/hk+OfySCa1nuO7WCnLUfj qY5tJhkttq6T3R4rpK4x8mKFtXKstP427tl3dF5L9JWHp6DdLVDx/DaHmYyjBseVPRX1YMRl/ 7F4XkPzsqFEPA8luyD5QInFOT5hEct5h7lNRBqrvbeUsiqr4qSkFeyTtVTsjVu3hA1wQHH3if il8VdaQUWEdy1oZIu0lXkzluWh4ldCcHuxZzPggzPu2FjYfsO25zH3h/qfyek1fwIKHLGdcLb JWvzt2vRZfmvNK+8TIxX+RQB8caWcpmRT6N9evjo1UX7DP3diPvcjqEJTkfxjSbIcmdZRUhhK DEVQ1IcwWyjD2pMfxeQwhJPp4FyUFDeQtG2K03039j2CfOIRNExGc8wLR/lVPWTXd+nlPcHRv SuWOc3eMsYOYy0EHu0kB0ekEu2Lfmvs9URv4oxthMTVehA4gNJz4VhF9lKAsvan3hbdMwfg3 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:152823 Archived-At: >> These operations would have to be automatized and improved as follows: >> >> Process a (minibuffer . child-frame) frame parameter to >> >> (1) make an _invisible_ top-level minibuffer-only frame similar to >> what we are doing in the (minibuffer . nil) case, >> >> (2) create the minibuffer-less parent frame with the minibuffer window >> set to the window made in (1), >> >> (3) reparent the minibuffer frame created in (1) and make it visible. > > Should this be a dedicated function, > e.g. make-frame-with-minibuffer-child. Or a behavior triggered by an > additional frame-parameter passed to the parent ? Ideally, the behavior would be triggered by a special value of the 'minibuffer' frame parameter specified via 'initial-frame-alist' or 'default-frame-alist'. On window systems where child frames are not supported, it would automatically fall back on the (minibuffer . nil) behavior. (minibuffer . child-frame) would be one way to specify that. Note that the value 'child-frame' would not get stored in the child-frame's minibuffer parameter: the parent frame's minibuffer parameter would become nil, the child frame's minibuffer parameter would become 'only'. All this would be done in 'frame-notice-user-settings' in frame.el independently from how we eventually try to get rid of the minibuffer frame. >> Then deleting the parent frame would >> >> (4) make the minibuffer frame invisible and top-level, >> >> (5) delete the parent frame, >> >> (6) delete the minibuffer frame if possible or make it visible if it >> still serves as minibuffer frame for another frame. >> >> (4)-(5) would have to handle the cases correctly where delete_frame >> (the C function) is called from Elisp (via C-x 5 0, for example) and >> from the window manager (by clicking the "x" on the title bar). The >> Elisp call would not shut down Emacs, the window manager call could. >> > It seems to me that this code should go into Fdelete_frame ? No. AFAICT we have to process the !other_frames (f, false, !NILP (force)) in delete_frame first (note that our minibuffer child frame is not reported by that call as separate frame). Only if that call succeeds (so another top-level frame exists) we'd make the minibuffer window top-level and invisible before it gets caught by the delete_frame call in /* Softly delete all frames with this frame as their parent frame or as their `delete-before' frame parameter value. */ FOR_EACH_FRAME (frames, frame1) if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f /* Process `delete-before' parameter iff FRAME is not a child frame. This avoids that we enter an infinite chain of mixed dependencies. */ || (nochild && EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame))) delete_frame (frame1, Qnil); and remember it in a Lisp variable say minibuffer_child_frame. Then delete_frame would do its normal job by deleting the parent frame and any actions related to that. Note that this could delete, by side-effect, our minibuffer_child_frame. At the end of delete_frame we'd check if our minibuffer_child_frame is still a live frame. If it has no other clients, we'd delete it via a separate delete_frame call. Otherwise, we'd make it visible. There are (at least) two tricky things to observe: This /* delete_frame_functions may have deleted any frame, including this one. */ if (!FRAME_LIVE_P (f)) return Qnil; must instead go to the end of delete_frame instead of trying to delete minibuffer_child_frame. And we must guarantee that minibuffer_child_frame becomes visible when an error occurs within delete_frame before it reaches the end. This would be done with the help of a record_unwind_protect form which would be roughly implemented as follows: At the top of delete-frame add a ptrdiff_t count = SPECPDL_INDEX (); When assigning minibuffer_child_frame do record_unwind_protect (make_frame_visible_if_live, child_frame); At the end add unbind_to (count, Qnil); make_frame_visible_if_live would then be a trivial function accepting a Lisp_Object frame argument and would call Fmake_frame_visible for that frame provided it is live. > What if we allow the deletion of a minibuffer frame, if it will not > violate the invariant that all frames have a minibuffer, i.e. because > the frame in question will be deleted some time later (because this > operation is already on the call-stack.). I don't know if this > temporary violation (i.e. between deleting the child-minibuffer and > deleting the parent) is a problem. Anyway, this would enable the user > to delete these kinds of frames normally, even if it looks jerky. Frame deletion is in C because it's extremely hairy and must be done in some sort of a atomic fashion. So any temporary violation of the "each frame must have a minibuffer window" rule is no solution at the present. > And then implement the special minibuffer-as-child-frame behavior and > logic via dedicated functions, which display and undsiplay these frames > nicely. (Still, delete-frame would have to be redirected to some proxy > handling this case.) If window manager calls (clicking the "x" on the title bar) are processed without problems (that is, delete parent and minibuffer child frame in one go - did you check that?) then we could have 'delete-frame' run a 'before-delete-frame-functions' hook. In that hook we could make the minibuffer top-level and invisible while 'after-delete-frame-functions' would take care of deleting the minibuffer frame or making it visible. But if anything bad happens, then 'after-make-frame-functions' would not get executed and the minibuffer frame stay invisible forever. Not making the minibuffer frame invisible, OTOH would show it for a short while somewhere on the desktop which doesn't look very professional IMO. martin