When a frame is both the child-frame and the minibuffer-frame of some
other frame, this other frame can not be delete anymore.
Starting from emacs -Q:
(defvar initial-frame (selected-frame))
;; Create the parent without minibuffer.
(defvar parent-frame (make-frame '((minibuffer . nil))))
;; Create the child as minibuffer-only.
(defvar child-frame (make-frame
`((parent-frame . ,parent-frame)
(minibuffer . only)
(height . 1)
(keep-ration . t))))
;; Make the child the minibuffer frame of the parent.
parent-frame `((minibuffer . ,(minibuffer-window child-frame))))
;; Situation: The parent/child frames can not be deleted anymore.
;; None of the following operations succeed.
;; Delete parent
;; Delete child
;; Delete both
;; "Attempt to delete a surrogate minibuffer frame" [3 times]
;; A workaround is to untie the child frame from its parent before
;; deleting it.
(set-frame-parameter child-frame 'parent-frame nil)
In GNU Emacs 26.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.30)
of 2018-07-05 built on juergen
Windowing system distributor 'The X.Org Foundation', version 11.0.12003000
System Description: Arch Linux
Mark set [2 times]
Mark saved where search started
Type "q" in help window to restore its previous buffer.
Mark set [2 times]
Making completion list...
'configure --prefix=/usr --sysconfdir=/etc --libexecdir=/usr/lib
--localstatedir=/var --with-x-toolkit=gtk3 --with-xft --with-modules
'CFLAGS=-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong
XPM JPEG TIFF GIF PNG RSVG IMAGEMAGICK SOUND GPM DBUS GSETTINGS NOTIFY
ACL GNUTLS LIBXML2 FREETYPE M17N_FLT LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS
GTK3 X11 MODULES THREADS LIBSYSTEMD LCMS2
value of $LANG: en_US.UTF-8
Major mode: Org
Minor modes in effect:
/home/politza/.emacs.d/usr/elpa/color-theme-solarized-20171024.1525/solarized-theme hides /home/politza/.emacs.d/usr/elpa/solarized-theme-20181025.1251/solarized-theme
/home/politza/.emacs.d/usr/plugins/filecache hides /usr/share/emacs/26.1/lisp/filecache
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-latex hides /usr/share/emacs/26.1/lisp/org/ob-latex
/home/politza/.emacs.d/usr/elpa/org-20181022/org-mobile hides /usr/share/emacs/26.1/lisp/org/org-mobile
/home/politza/.emacs.d/usr/elpa/org-20181022/org-eww hides /usr/share/emacs/26.1/lisp/org/org-eww
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-screen hides /usr/share/emacs/26.1/lisp/org/ob-screen
/home/politza/.emacs.d/usr/elpa/org-20181022/org-plot hides /usr/share/emacs/26.1/lisp/org/org-plot
/home/politza/.emacs.d/usr/elpa/org-20181022/org-capture hides /usr/share/emacs/26.1/lisp/org/org-capture
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-org hides /usr/share/emacs/26.1/lisp/org/ob-org
/home/politza/.emacs.d/usr/elpa/org-20181022/ox-ascii hides /usr/share/emacs/26.1/lisp/org/ox-ascii
/home/politza/.emacs.d/usr/elpa/org-20181022/org-agenda hides /usr/share/emacs/26.1/lisp/org/org-agenda
/home/politza/.emacs.d/usr/elpa/org-20181022/org-lint hides /usr/share/emacs/26.1/lisp/org/org-lint
/home/politza/.emacs.d/usr/elpa/org-20181022/org-protocol hides /usr/share/emacs/26.1/lisp/org/org-protocol
/home/politza/.emacs.d/usr/elpa/org-20181022/ox-icalendar hides /usr/share/emacs/26.1/lisp/org/ox-icalendar
/home/politza/.emacs.d/usr/elpa/org-20181022/org-gnus hides /usr/share/emacs/26.1/lisp/org/org-gnus
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-io hides /usr/share/emacs/26.1/lisp/org/ob-io
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-comint hides /usr/share/emacs/26.1/lisp/org/ob-comint
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-forth hides /usr/share/emacs/26.1/lisp/org/ob-forth
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-matlab hides /usr/share/emacs/26.1/lisp/org/ob-matlab
/home/politza/.emacs.d/usr/elpa/org-20181022/org-compat hides /usr/share/emacs/26.1/lisp/org/org-compat
/home/politza/.emacs.d/usr/elpa/org-20181022/org-src hides /usr/share/emacs/26.1/lisp/org/org-src
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-stan hides /usr/share/emacs/26.1/lisp/org/ob-stan
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-ditaa hides /usr/share/emacs/26.1/lisp/org/ob-ditaa
/home/politza/.emacs.d/usr/elpa/org-20181022/org-bibtex hides /usr/share/emacs/26.1/lisp/org/org-bibtex
/home/politza/.emacs.d/usr/elpa/org-20181022/org-feed hides /usr/share/emacs/26.1/lisp/org/org-feed
/home/politza/.emacs.d/usr/elpa/org-20181022/org-bbdb hides /usr/share/emacs/26.1/lisp/org/org-bbdb
/home/politza/.emacs.d/usr/elpa/org-20181022/ox-texinfo hides /usr/share/emacs/26.1/lisp/org/ox-texinfo
/home/politza/.emacs.d/usr/elpa/org-20181022/org-entities hides /usr/share/emacs/26.1/lisp/org/org-entities
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-css hides /usr/share/emacs/26.1/lisp/org/ob-css
/home/politza/.emacs.d/usr/elpa/org-20181022/org-macro hides /usr/share/emacs/26.1/lisp/org/org-macro
/home/politza/.emacs.d/usr/elpa/org-20181022/org-crypt hides /usr/share/emacs/26.1/lisp/org/org-crypt
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-core hides /usr/share/emacs/26.1/lisp/org/ob-core
/home/politza/.emacs.d/usr/elpa/org-20181022/ox-latex hides /usr/share/emacs/26.1/lisp/org/ox-latex
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-sass hides /usr/share/emacs/26.1/lisp/org/ob-sass
/home/politza/.emacs.d/usr/elpa/org-20181022/org-mouse hides /usr/share/emacs/26.1/lisp/org/org-mouse
/home/politza/.emacs.d/usr/elpa/org-20181022/org-info hides /usr/share/emacs/26.1/lisp/org/org-info
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-shen hides /usr/share/emacs/26.1/lisp/org/ob-shen
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-sql hides /usr/share/emacs/26.1/lisp/org/ob-sql
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-abc hides /usr/share/emacs/26.1/lisp/org/ob-abc
/home/politza/.emacs.d/usr/elpa/org-20181022/ox-html hides /usr/share/emacs/26.1/lisp/org/ox-html
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-makefile hides /usr/share/emacs/26.1/lisp/org/ob-makefile
/home/politza/.emacs.d/usr/elpa/org-20181022/org-colview hides /usr/share/emacs/26.1/lisp/org/org-colview
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-plantuml hides /usr/share/emacs/26.1/lisp/org/ob-plantuml
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-scheme hides /usr/share/emacs/26.1/lisp/org/ob-scheme
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-ref hides /usr/share/emacs/26.1/lisp/org/ob-ref
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-picolisp hides /usr/share/emacs/26.1/lisp/org/ob-picolisp
/home/politza/.emacs.d/usr/elpa/org-20181022/ob hides /usr/share/emacs/26.1/lisp/org/ob
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-js hides /usr/share/emacs/26.1/lisp/org/ob-js
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-octave hides /usr/share/emacs/26.1/lisp/org/ob-octave
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-calc hides /usr/share/emacs/26.1/lisp/org/ob-calc
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-eval hides /usr/share/emacs/26.1/lisp/org/ob-eval
/home/politza/.emacs.d/usr/elpa/org-20181022/org-indent hides /usr/share/emacs/26.1/lisp/org/org-indent
/home/politza/.emacs.d/usr/elpa/org-20181022/org-eshell hides /usr/share/emacs/26.1/lisp/org/org-eshell
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-mscgen hides /usr/share/emacs/26.1/lisp/org/ob-mscgen
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-vala hides /usr/share/emacs/26.1/lisp/org/ob-vala
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-C hides /usr/share/emacs/26.1/lisp/org/ob-C
/home/politza/.emacs.d/usr/elpa/org-20181022/org-list hides /usr/share/emacs/26.1/lisp/org/org-list
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-lisp hides /usr/share/emacs/26.1/lisp/org/ob-lisp
/home/politza/.emacs.d/usr/elpa/org-20181022/ox-publish hides /usr/share/emacs/26.1/lisp/org/ox-publish
/home/politza/.emacs.d/usr/elpa/org-20181022/org-docview hides /usr/share/emacs/26.1/lisp/org/org-docview
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-keys hides /usr/share/emacs/26.1/lisp/org/ob-keys
/home/politza/.emacs.d/usr/elpa/org-20181022/ox-org hides /usr/share/emacs/26.1/lisp/org/ox-org
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-asymptote hides /usr/share/emacs/26.1/lisp/org/ob-asymptote
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-ocaml hides /usr/share/emacs/26.1/lisp/org/ob-ocaml
/home/politza/.emacs.d/usr/elpa/org-20181022/org-loaddefs hides /usr/share/emacs/26.1/lisp/org/org-loaddefs
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-shell hides /usr/share/emacs/26.1/lisp/org/ob-shell
/home/politza/.emacs.d/usr/elpa/org-20181022/org-habit hides /usr/share/emacs/26.1/lisp/org/org-habit
/home/politza/.emacs.d/usr/elpa/org-20181022/org-clock hides /usr/share/emacs/26.1/lisp/org/org-clock
/home/politza/.emacs.d/usr/elpa/org-20181022/org-pcomplete hides /usr/share/emacs/26.1/lisp/org/org-pcomplete
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-lilypond hides /usr/share/emacs/26.1/lisp/org/ob-lilypond
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-tangle hides /usr/share/emacs/26.1/lisp/org/ob-tangle
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-hledger hides /usr/share/emacs/26.1/lisp/org/ob-hledger
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-dot hides /usr/share/emacs/26.1/lisp/org/ob-dot
/home/politza/.emacs.d/usr/elpa/org-20181022/ox hides /usr/share/emacs/26.1/lisp/org/ox
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-python hides /usr/share/emacs/26.1/lisp/org/ob-python
/home/politza/.emacs.d/usr/elpa/org-20181022/org-macs hides /usr/share/emacs/26.1/lisp/org/org-macs
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-groovy hides /usr/share/emacs/26.1/lisp/org/ob-groovy
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-J hides /usr/share/emacs/26.1/lisp/org/ob-J
/home/politza/.emacs.d/usr/elpa/org-20181022/org-id hides /usr/share/emacs/26.1/lisp/org/org-id
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-clojure hides /usr/share/emacs/26.1/lisp/org/ob-clojure
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-perl hides /usr/share/emacs/26.1/lisp/org/ob-perl
/home/politza/.emacs.d/usr/elpa/org-20181022/org-w3m hides /usr/share/emacs/26.1/lisp/org/org-w3m
/home/politza/.emacs.d/usr/elpa/org-20181022/ox-md hides /usr/share/emacs/26.1/lisp/org/ox-md
/home/politza/.emacs.d/usr/elpa/org-20181022/org-mhe hides /usr/share/emacs/26.1/lisp/org/org-mhe
/home/politza/.emacs.d/usr/elpa/org-20181022/org-attach hides /usr/share/emacs/26.1/lisp/org/org-attach
/home/politza/.emacs.d/usr/elpa/org-20181022/org-datetree hides /usr/share/emacs/26.1/lisp/org/org-datetree
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-ledger hides /usr/share/emacs/26.1/lisp/org/ob-ledger
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-sed hides /usr/share/emacs/26.1/lisp/org/ob-sed
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-lob hides /usr/share/emacs/26.1/lisp/org/ob-lob
/home/politza/.emacs.d/usr/elpa/org-20181022/org-table hides /usr/share/emacs/26.1/lisp/org/org-table
/home/politza/.emacs.d/usr/elpa/org-20181022/org-archive hides /usr/share/emacs/26.1/lisp/org/org-archive
/home/politza/.emacs.d/usr/elpa/org-20181022/org-version hides /usr/share/emacs/26.1/lisp/org/org-version
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-awk hides /usr/share/emacs/26.1/lisp/org/ob-awk
/home/politza/.emacs.d/usr/elpa/org-20181022/ox-odt hides /usr/share/emacs/26.1/lisp/org/ox-odt
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-maxima hides /usr/share/emacs/26.1/lisp/org/ob-maxima
/home/politza/.emacs.d/usr/elpa/org-20181022/org-footnote hides /usr/share/emacs/26.1/lisp/org/org-footnote
/home/politza/.emacs.d/usr/elpa/org-20181022/org-irc hides /usr/share/emacs/26.1/lisp/org/org-irc
/home/politza/.emacs.d/usr/elpa/org-20181022/org-ctags hides /usr/share/emacs/26.1/lisp/org/org-ctags
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-ebnf hides /usr/share/emacs/26.1/lisp/org/ob-ebnf
/home/politza/.emacs.d/usr/elpa/org-20181022/org-install hides /usr/share/emacs/26.1/lisp/org/org-install
/home/politza/.emacs.d/usr/elpa/org-20181022/org hides /usr/share/emacs/26.1/lisp/org/org
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-java hides /usr/share/emacs/26.1/lisp/org/ob-java
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-emacs-lisp hides /usr/share/emacs/26.1/lisp/org/ob-emacs-lisp
/home/politza/.emacs.d/usr/elpa/org-20181022/ox-man hides /usr/share/emacs/26.1/lisp/org/ox-man
/home/politza/.emacs.d/usr/elpa/org-20181022/ox-beamer hides /usr/share/emacs/26.1/lisp/org/ox-beamer
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-sqlite hides /usr/share/emacs/26.1/lisp/org/ob-sqlite
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-exp hides /usr/share/emacs/26.1/lisp/org/ob-exp
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-haskell hides /usr/share/emacs/26.1/lisp/org/ob-haskell
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-gnuplot hides /usr/share/emacs/26.1/lisp/org/ob-gnuplot
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-ruby hides /usr/share/emacs/26.1/lisp/org/ob-ruby
/home/politza/.emacs.d/usr/elpa/org-20181022/org-inlinetask hides /usr/share/emacs/26.1/lisp/org/org-inlinetask
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-lua hides /usr/share/emacs/26.1/lisp/org/ob-lua
/home/politza/.emacs.d/usr/elpa/org-20181022/org-timer hides /usr/share/emacs/26.1/lisp/org/org-timer
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-R hides /usr/share/emacs/26.1/lisp/org/ob-R
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-coq hides /usr/share/emacs/26.1/lisp/org/ob-coq
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-table hides /usr/share/emacs/26.1/lisp/org/ob-table
/home/politza/.emacs.d/usr/elpa/org-20181022/org-duration hides /usr/share/emacs/26.1/lisp/org/org-duration
/home/politza/.emacs.d/usr/elpa/org-20181022/org-rmail hides /usr/share/emacs/26.1/lisp/org/org-rmail
/home/politza/.emacs.d/usr/elpa/org-20181022/org-element hides /usr/share/emacs/26.1/lisp/org/org-element
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-fortran hides /usr/share/emacs/26.1/lisp/org/ob-fortran
/home/politza/.emacs.d/usr/elpa/org-20181022/ob-processing hides /usr/share/emacs/26.1/lisp/org/ob-processing
/home/politza/.emacs.d/usr/elpa/org-20181022/org-faces hides /usr/share/emacs/26.1/lisp/org/org-faces
(shadow sort gnus-cite mail-extr nndraft nnmh utf-7 network-stream nsm
starttls nnfolder nnnil gnus-agent gnus-srvr gnus-score score-mode
nnvirtual nntp gnus-cache gnus-msg gnus-art mm-uu mml2015 mm-view
mml-smime smime dig mailcap emacsbug sendmail org-rmail org-mhe org-irc
org-info org-gnus nnir gnus-sum gnus-group gnus-undo gnus-start
gnus-cloud nnimap nnmail mail-source tls gnutls utf7 netrc nnoo
gnus-spec gnus-int gnus-range message rmc puny rfc822 mml mml-sec epa
epg mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev
gmm-utils mailheader gnus-win gnus nnheader gnus-util rmail
rmail-loaddefs rfc2047 rfc2045 ietf-drums mail-utils mm-util mail-prsvr
org-docview doc-view org-bibtex bibtex org-bbdb org-w3m info-look
eieio-opt speedbar sb-image ezimage dframe ispell misearch multi-isearch
dabbrev cl-print rect help-fns radix-tree vc-git diff-mode cc-mode
cc-fonts cc-guess cc-menus cc-cmds cc-styles cc-align cc-engine cc-vars
cc-defs view files-x tramp-cache tramp-sh tramp tramp-compat
tramp-loaddefs trampver ucs-normalize shell parse-time filecache dictcc
ivy delsel colir color ivy-overlay ffap what derived what-conf company
pcase racer pos-tip thingatpt f s etags xref project dash rust-mode json
map gud ediff-merg ediff-wind ediff-diff ediff-mult ediff-help
ediff-init ediff-util ediff tex dbus xml crm pdf-occur ibuf-ext ibuffer
ibuffer-loaddefs tablist tablist-filter semantic/wisent/comp
semantic/wisent semantic/wisent/wisent semantic/util-modes semantic/util
semantic semantic/tag semantic/lex semantic/fw mode-local cedet
pdf-isearch let-alist pdf-misc imenu pdf-tools cus-edit wid-edit
pdf-view bookmark pp jka-compr pdf-cache pdf-info tq pdf-util image-mode
restart-emacs desktop frameset org-bullets ob-plantuml
completion-dyninit subr-x bind-key man cl-extra help-mode
use-package-core dired-x dired dired-loaddefs server saveplace savehist
edmacro kmacro grep cus-start cus-load org-element avl-tree generator
org advice org-macro org-footnote org-pcomplete pcomplete org-list
org-faces org-entities noutline outline easy-mmode org-version
ob-emacs-lisp ob ob-tangle org-src ob-ref ob-lob ob-table ob-keys ob-exp
ob-comint ob-core ob-eval org-compat org-macs org-loaddefs format-spec
find-func cal-menu calendar cal-loaddefs elec-pair compile comint
ansi-color ring finder-inf tex-site rx info package easymenu epg-config
url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs
eieio-loaddefs password-cache url-vars seq byte-opt gv bytecomp
byte-compile cconv cl-loaddefs cl-lib time-date mule-util tooltip eldoc
electric uniquify ediff-hook vc-hooks lisp-float-type mwheel term/x-win
x-win term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode elisp-mode lisp-mode
prog-mode register page menu-bar rfn-eshadow isearch timer select
scroll-bar mouse jit-lock font-lock syntax facemenu font-core
term/tty-colors frame cl-generic cham georgian utf-8-lang misc-lang
vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932
hebrew greek romanian slovak czech european ethiopic indian cyrillic
chinese composite charscript charprop case-table epa-hook jka-cmpr-hook
help simple abbrev obarray minibuffer cl-preloaded nadvice loaddefs
button faces cus-face macroexp files text-properties overlay sha1 md5
base64 format env code-pages mule custom widget hashtable-print-readable
backquote dbusbind inotify lcms2 dynamic-setting system-font-setting
font-render-setting move-toolbar gtk x-toolkit x multi-tty
((conses 16 655055 55393)
(symbols 48 53438 1)
(miscs 40 1993 1159)
(strings 32 178914 10155)
(string-bytes 1 5527254)
(vectors 16 82566)
(vector-slots 8 1416768 33222)
(floats 8 534 500)
(intervals 56 5365 777)
(buffers 992 34))
> When a frame is both the child-frame and the minibuffer-frame of some
> other frame, this other frame can not be delete anymore.
> (keep-ration . t))))
'keep-ratio', not 'keep-ration' - but it's not useful here anyway IMO.
You probably want to make sure that the child frame auto-resizes,
though. I wrote the corresponding code already but it still needs
some work: It doesn't yet look at the height of the parent frame and
probably should allow for aligning at the bottom of the latter as
> ;; A workaround is to untie the child frame from its parent before
> ;; deleting it.
> (set-frame-parameter child-frame 'parent-frame nil)
> (delete-frame parent-frame)
Correct. But that's just the inverse from what you did when you
created the parent-child configuration. So it's not a workaround but
the canonical way. BTW, I wrote the reparent code to accomplish doing
precisely what you did here, reparenting doesn't make much sense
elsewhere. And I plan to document that. But without the possibility
to auto-resize child frames, the whole concept is not very attractive
martin rudalics <[hidden email]> writes:
>> (keep-ration . t))))
I must have been hungry.
> 'keep-ratio', not 'keep-ration' - but it's not useful here anyway IMO.
> You probably want to make sure that the child frame auto-resizes,
> I wrote the corresponding code already but it still needs some work: [...]
Are you talking about a different feature here ? Because, this is what I
understand `keep-ratio' is supposed to be doing.
> Correct. But that's just the inverse from what you did when you
> created the parent-child configuration. So it's not a workaround but
> the canonical way. BTW, I wrote the reparent code to accomplish doing
> precisely what you did here, reparenting doesn't make much sense
So, you are saying it's supposed to be like that ? Them, I don't see a
reason, why Emacs should disallow deleting the minibuffer-frame as a
child-frame in this case.
> Are you talking about a different feature here ? Because, this is what I
> understand `keep-ratio' is supposed to be doing.
'keep-ratio' simply correlates the sizes of a child and its parent
frame. If you make a parent frame half its size, 'keep-ratio' makes
its child frames half their size as well. What I mean is the usual
expanding/shrinking of the minibuffer window you can observe on a
normal minibuffer equipped frame. For example, via (message"\n\n").
> So, you are saying it's supposed to be like that ?
> Them, I don't see a
> reason, why Emacs should disallow deleting the minibuffer-frame as a
> child-frame in this case.
For internal reasons each live frame must have a minibuffer window.
This is hardcoded in a couple of internal routines and if you remove
that restriction (it's the "Attempt to delete a surrogate minibuffer
frame" in frame.c) Emacs will crash soon after that. Note that a
child frame minibuffer is handled like a normal minibuffer-only frame
in this regard.
martin rudalics <[hidden email]> writes:
> [...] What I mean is the usual expanding/shrinking of the minibuffer
> window you can observe on a normal minibuffer equipped frame. For
> example, via (message"\n\n").
> For internal reasons each live frame must have a minibuffer window.
> This is hardcoded in a couple of internal routines and if you remove
> that restriction (it's the "Attempt to delete a surrogate minibuffer
> frame" in frame.c) [...]
I don't mean to remove that restriction. But in this case, where the
parent is deleted and the child is the parent's minibuffer-frame (and
there are no other frame using this minibuffer-frame) this restriction
doesn't seem to apply, at least on a conceptual level.
From the point of a user, this means that he either needs to advise
`delete-frame' or use a different command in order to delete these kinds
>> For internal reasons each live frame must have a minibuffer window.
>> This is hardcoded in a couple of internal routines and if you remove
>> that restriction (it's the "Attempt to delete a surrogate minibuffer
>> frame" in frame.c) [...]
> I don't mean to remove that restriction. But in this case, where the
> parent is deleted and the child is the parent's minibuffer-frame (and
> there are no other frame using this minibuffer-frame) this restriction
> doesn't seem to apply, at least on a conceptual level.
Agreed. But the only way to delete the parent frame is to do what you
did - untie the minibuffer frame first by making it top-level and then
delete its former parent. The problems with this are the same you
probably see when you create the minibuffer frame: the minibuffer
frame becomes first visible on the desktop as a top-level frame before
it gets moved and subordinated to the parent frame. When deleting the
parent frame you see the inverse effect: the minibuffer frame becomes
top-level on the desktop and stays there in some orphaned fashion
until you eventually kill it.
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.
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.
To process (6) we would maybe also want an 'auto-delete-minibuffer'
frame parameter (which could then be also used for non-child-frame
Finally, any such code will have to process the 'delete-before' frame
parameter appropriately to avoid running into an infinite loop of
failed deletion attempts.
>>From the point of a user, this means that he either needs to advise
> `delete-frame' or use a different command in order to delete these kinds
> of frames.
Indeed. Patches welcome.
Thanks for the detailed explanation. I was looking for a way to have
the minibuffer at the top of the frame, which you'd probably already
martin rudalics <[hidden email]> writes:
> 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 ?
It seems to me that this code should go into Fdelete_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.
> To process (6) we would maybe also want an 'auto-delete-minibuffer'
> frame parameter (which could then be also used for non-child-frame
> minibuffer-only frames).
> Finally, any such code will have to process the 'delete-before' frame
> parameter appropriately to avoid running into an infinite loop of
> failed deletion attempts.
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.
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.)
>> 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)
(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
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
>> 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
/* 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
&& 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
if (!FRAME_LIVE_P (f))
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
> 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.
In reply to this post by Andreas Politz, INF|INF-I-2
> When a frame is both the child-frame and the minibuffer-frame of some
> other frame, this other frame can not be delete anymore.
I think I fixed this now on master. Please have a look.
By using a '(minibuffer . child-frame) frame parameter, creating the
minibuffer child frame should proceed without glitches now. I intend
to soon add code for fitting minibuffer child frames to the contents
of their buffers.
In reply to this post by Andreas Politz, INF|INF-I-2
> I think I fixed this now on master. Please have a look.
Unfortunately the fix broke builds configured with
--enable-gcc-warnings, as GCC complains about the use of an
uninitialized variable that appears to be a typo in the fix. I installed
the attached patch to unbreak the build; please check it to make sure
that I understood the intent of the fix correctly.
It's a good idea to use './configure --enable-gcc-warnings' when making
changes to the C code in Emacs, as GCC is reasonably good at catching
typos like this, and typically does not generate too many false alarms.
0001-Fix-typo-in-fix-for-Bug-33498.patch (877 bytes) Download Attachment
> Unfortunately the fix broke builds configured with
> --enable-gcc-warnings, as GCC complains about the use of an
> uninitialized variable that appears to be a typo in the fix. I installed
> the attached patch to unbreak the build; please check it to make sure
> that I understood the intent of the fix correctly.
Many thanks for catching this, your fix is correct. Unfortunately,
it's impossible for me to trigger a crash in a running Emacs since
frame1 apparently gets assigned the "correct" value in one of the
loops executed before. Using these initial settings
(setq initial-frame-alist '((minibuffer . child-frame)))
(setq default-frame-alist '((minibuffer)))
and subsequently evaluating
;; Assign initial and minibuffer frame.
(setq initial-frame (selected-frame))
(setq minibuffer-frame (window-frame (minibuffer-window)))
;; Make a new frame whose minibuffer window should be on
;; Make minibuffer frame invisible.
;; Delete initial frame.
the last one could trigger a crash but minibuffer-frame just becomes
visible as expected because frame1 _is_ minibuffer_child_frame there.
> It's a good idea to use './configure --enable-gcc-warnings' when making
> changes to the C code in Emacs, as GCC is reasonably good at catching
> typos like this, and typically does not generate too many false alarms.
I build with
'configure --prefix=/c/emacs-git/trunk/dbg --with-gnutls=no
--without-pop --enable-checking=yes --enable-gcc-warnings=warn-only
--enable-check-lisp-object-type=warn-only 'CFLAGS=-O0 -g3
ever since but it seems that gcc 4.8.1 is simply too old to catch such
subtle bugs (just verified by building with the buggy version again).
Thanks again for the fix, martin
In reply to this post by martin rudalics
martin rudalics <[hidden email]> writes:
> By using a '(minibuffer . child-frame) frame parameter, creating the
> minibuffer child frame should proceed without glitches now.
Yes, that seems to work now.
> I intend to soon add code for fitting minibuffer child frames to the
> contents of their buffers.
And I am looking forward to it.
|Free forum by Nabble||Edit this page|