unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
@ 2018-11-25 11:43 Andreas Politz
  2018-11-25 17:40 ` martin rudalics
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Andreas Politz @ 2018-11-25 11:43 UTC (permalink / raw)
  To: 33498


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:

#+BEGIN_SRC emacs-lisp
  (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.
  (modify-frame-parameters
   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
  (with-demoted-errors "%S"
    (delete-frame parent-frame))
  ;; Delete child
  (with-demoted-errors "%S"
    (delete-frame child-frame))
  ;; Delete both
  (with-demoted-errors "%S"
    (delete-other-frames initial-frame))

  (switch-to-buffer "*Messages*")
  ;; "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)
  (delete-frame parent-frame)
#+END_SRC



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

Recent messages:
Mark set
Auto-saving...done
Mark set [2 times]
Quit
Undo!
Mark saved where search started
Type "q" in help window to restore its previous buffer.
Auto-saving...
Mark set [2 times]
Making completion list...

Configured using:
 '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
 -fno-plt' CPPFLAGS=-D_FORTIFY_SOURCE=2
 LDFLAGS=-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now'

Configured features:
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

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Org

Minor modes in effect:
  diff-auto-refine-mode: t
  shell-dirtrack-mode: t
  what-mode: t
  TeX-PDF-mode: t
  pdf-occur-global-minor-mode: t
  org-bullets-mode: t
  sane/sync-mail-mode: t
  override-global-mode: t
  save-place-mode: t
  savehist-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  column-number-mode: t
  line-number-mode: t
  auto-fill-function: org-auto-fill-function
  transient-mark-mode: t

Load-path shadows:
/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

Features:
(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
make-network-process emacs)

Memory information:
((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))





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2018-11-25 11:43 bug#33498: 26.1; Unable to delete minibuffer-only+child frames Andreas Politz
@ 2018-11-25 17:40 ` martin rudalics
  2018-11-25 18:28   ` Andreas Politz
  2019-03-05 10:12 ` martin rudalics
  2019-03-06 19:07 ` Paul Eggert
  2 siblings, 1 reply; 13+ messages in thread
From: martin rudalics @ 2018-11-25 17:40 UTC (permalink / raw)
  To: Andreas Politz, 33498

 > When a frame is both the child-frame and the minibuffer-frame of some
 > other frame, this other frame can not be delete anymore.

Right.

 >                           (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
well.

 >    ;; 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
yet.

Thanks, martin





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2018-11-25 17:40 ` martin rudalics
@ 2018-11-25 18:28   ` Andreas Politz
  2018-11-25 18:57     ` martin rudalics
  0 siblings, 1 reply; 13+ messages in thread
From: Andreas Politz @ 2018-11-25 18:28 UTC (permalink / raw)
  To: martin rudalics; +Cc: 33498

martin rudalics <rudalics@gmx.at> 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,
> though.  
> 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
> elsewhere.

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.

Andreas





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2018-11-25 18:28   ` Andreas Politz
@ 2018-11-25 18:57     ` martin rudalics
  2018-11-25 19:33       ` Andreas Politz
  0 siblings, 1 reply; 13+ messages in thread
From: martin rudalics @ 2018-11-25 18:57 UTC (permalink / raw)
  To: Andreas Politz; +Cc: 33498

 > 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 ?

Yes.

 > 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





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2018-11-25 18:57     ` martin rudalics
@ 2018-11-25 19:33       ` Andreas Politz
  2018-11-26  9:31         ` martin rudalics
  0 siblings, 1 reply; 13+ messages in thread
From: Andreas Politz @ 2018-11-25 19:33 UTC (permalink / raw)
  To: martin rudalics; +Cc: 33498

martin rudalics <rudalics@gmx.at> 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").

I see.

> 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
of frames.

Andreas





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2018-11-25 19:33       ` Andreas Politz
@ 2018-11-26  9:31         ` martin rudalics
  2018-11-26 18:59           ` Andreas Politz
  0 siblings, 1 reply; 13+ messages in thread
From: martin rudalics @ 2018-11-26  9:31 UTC (permalink / raw)
  To: Andreas Politz; +Cc: 33498

 >> 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
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.

 >>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.

martin





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2018-11-26  9:31         ` martin rudalics
@ 2018-11-26 18:59           ` Andreas Politz
  2018-11-27 10:14             ` martin rudalics
  0 siblings, 1 reply; 13+ messages in thread
From: Andreas Politz @ 2018-11-26 18:59 UTC (permalink / raw)
  To: martin rudalics; +Cc: 33498

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
guessed.

martin rudalics <rudalics@gmx.at> 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 ?

> 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 ?

> 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.)

Andreas





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2018-11-26 18:59           ` Andreas Politz
@ 2018-11-27 10:14             ` martin rudalics
  0 siblings, 0 replies; 13+ messages in thread
From: martin rudalics @ 2018-11-27 10:14 UTC (permalink / raw)
  To: Andreas Politz; +Cc: 33498

 >> 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





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2018-11-25 11:43 bug#33498: 26.1; Unable to delete minibuffer-only+child frames Andreas Politz
  2018-11-25 17:40 ` martin rudalics
@ 2019-03-05 10:12 ` martin rudalics
  2019-03-13 20:24   ` Andreas Politz
  2019-03-06 19:07 ` Paul Eggert
  2 siblings, 1 reply; 13+ messages in thread
From: martin rudalics @ 2019-03-05 10:12 UTC (permalink / raw)
  To: Andreas Politz, 33498

 > 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.

martin





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2018-11-25 11:43 bug#33498: 26.1; Unable to delete minibuffer-only+child frames Andreas Politz
  2018-11-25 17:40 ` martin rudalics
  2019-03-05 10:12 ` martin rudalics
@ 2019-03-06 19:07 ` Paul Eggert
  2019-03-07  8:28   ` martin rudalics
  2 siblings, 1 reply; 13+ messages in thread
From: Paul Eggert @ 2019-03-06 19:07 UTC (permalink / raw)
  To: martin rudalics; +Cc: 33498

[-- Attachment #1: Type: text/plain, Size: 581 bytes --]

> 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.


[-- Attachment #2: 0001-Fix-typo-in-fix-for-Bug-33498.patch --]
[-- Type: text/x-patch, Size: 849 bytes --]

From 62879cbeae0221033a40d9f66e08673e4975e332 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 6 Mar 2019 11:04:57 -0800
Subject: [PATCH] Fix typo in fix for Bug#33498

* src/frame.c (delete_frame): Fix typo in previous patch,
which caused GCC to complain about the use of an uninitialized
variable.
---
 src/frame.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/frame.c b/src/frame.c
index 3d83dc0a0d..1219569068 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -2236,7 +2236,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
 		     for at least one other frame - so make it visible
 		     and quit.  */
 		  if (!FRAME_VISIBLE_P (f1) && !FRAME_ICONIFIED_P (f1))
-		    Fmake_frame_visible (frame1);
+		    Fmake_frame_visible (minibuffer_child_frame);
 
 		  return Qnil;
 		}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2019-03-06 19:07 ` Paul Eggert
@ 2019-03-07  8:28   ` martin rudalics
  0 siblings, 0 replies; 13+ messages in thread
From: martin rudalics @ 2019-03-07  8:28 UTC (permalink / raw)
  To: Paul Eggert; +Cc: 33498

 > 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
;; minibuffer-frame.
(make-frame)
;; Make minibuffer frame invisible.
(make-frame-invisible minibuffer-frame)
;; Delete initial frame.
(delete-frame 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

Configured using:
  '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
  -Wno-logical-op''

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





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2019-03-05 10:12 ` martin rudalics
@ 2019-03-13 20:24   ` Andreas Politz
  2019-04-23  8:46     ` martin rudalics
  0 siblings, 1 reply; 13+ messages in thread
From: Andreas Politz @ 2019-03-13 20:24 UTC (permalink / raw)
  To: martin rudalics; +Cc: 33498

martin rudalics <rudalics@gmx.at> 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.

Thanks,
Andreas





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#33498: 26.1; Unable to delete minibuffer-only+child frames
  2019-03-13 20:24   ` Andreas Politz
@ 2019-04-23  8:46     ` martin rudalics
  0 siblings, 0 replies; 13+ messages in thread
From: martin rudalics @ 2019-04-23  8:46 UTC (permalink / raw)
  To: Andreas Politz; +Cc: 33498

[-- Attachment #1: Type: text/plain, Size: 680 bytes --]

tags 33498 fixed
close 33498 27.1
quit

 >> By using a '(minibuffer . child-frame) frame parameter, creating the
 >> minibuffer child frame should proceed without glitches now.
 >
 > Yes, that seems to work now.

OK.  Trying to close this bug 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.

Customizing 'resize-mini-frames' allows to do that now.  I attach a
minor mode which I'm using for some while now that allows to put a
minibuffer child frame on the top or bottom of the currently selected
window and hide it whenever it's not used.  If you are on Emacs 27
try it.

martin

[-- Attachment #2: pop-up-mini.el --]
[-- Type: text/plain, Size: 24439 bytes --]

;;; pop-up-mini.el --- pop up mini window in child frame -*- lexical-binding:t -*-

;; Copyright (C) 2019  Free Software Foundation, Inc.

;; Author: Martin Rudalics <rudalics@gmx.at>
;; Keywords: frames, minibuffers, windows
;; Version: 1.0
;; Package-Requires: ((emacs "27.1"))

;; pop-up-mini.el is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 3, or (at
;; your option) any later version.

;; pop-up-mini.el is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; Minor mode to pop up minibuffer and echo area in a child frame of
;; the selected frame.  This mode automatizes the following behaviors:
;;
;; - Reparent child frame when switching frames.
;;
;; - Facultatively host child frame at the bottom or top of selected
;;   window or selected frame's main or root window.
;;
;; - Resize and reposition child frame corresponding to size of its
;;   text and/or host window.
;;
;; - Hide empty child frame.
;;
;; A sample form with recommended variable settings for customizing
;; the .emacs init file is included at the end of this file.

;; Note: This file will work only with Emacs 27.1 and higher.

;;; Code:

(defvar pop-up-mini-mode)

(defvar pop-up-mini-frame nil
  "The minibuffer child-frame of 'pop-up-mini-mode'.
Usually displayed as child frame of the selected frame.")

(defvar pop-up-mini-window nil
  "The root window of 'pop-up-mini-frame'.")

(defgroup pop-up-mini nil
  "Customization group for 'pop-up-mini-mode'."
  :version "27.1"
  :group 'convenience
  :group 'frames)

(defun pop-up-mini--set-value (symbol value)
  "Helper function for customizing 'pop-up-mini-mode' options."
  (set-default symbol value)
  (cond
   ((not (frame-live-p pop-up-mini-frame)))
   ((eq symbol 'pop-up-mini-internal-border)
    (set-face-background 'internal-border value pop-up-mini-frame))
   ((frame-visible-p pop-up-mini-frame)
    (when (frame-live-p (frame-parent pop-up-mini-frame))
      (pop-up-mini-move (frame-parent pop-up-mini-frame))))))

(defcustom pop-up-mini-host 'selected
  "Type of window hosting 'pop-up-mini-frame'.
Choices are

'selected' - the selected window

'main' - the selected frame's main window

'root' - the selected frame's root window

Note that both 'main' and 'root' may overwrite the mode lines of
the windows at the bottom of the frame."
  :type '(choice (const selected)
                 (const main)
                 (const root))
  :initialize 'custom-initialize-default
  :set 'pop-up-mini--set-value
  :version "27.1"
  :group 'pop-up-mini)

(defcustom pop-up-mini-host-min-width 20
  "Minimum width of host window for 'pop-up-mini-frame'.
If the window designated by 'pop-up-mini-host' is not as wide as
specified by this option, rehost 'pop-up-mini-frame' at the main
or root window of its parent frame."
  :type 'integer
  :initialize 'custom-initialize-default
  :set 'pop-up-mini--set-value
  :version "27.1"
  :group 'pop-up-mini)

(defcustom pop-up-mini-host-min-height 3
  "Minimum height of of host window for 'pop-up-mini-frame'.
If the window designated by 'pop-up-mini-host' is not as high as
specified by this option, rehost 'pop-up-mini-frame' at the main
or root window of its parent frame."
  :type 'integer
  :initialize 'custom-initialize-default
  :set 'pop-up-mini--set-value
  :version "27.1"
  :group 'pop-up-mini)

(defcustom pop-up-mini-rehost-to-fit t
  "If non-nil, rehost 'pop-up-mini-frame' when its text does not fit.
If this option is non-nil, 'pop-up-mini-host' equals 'selected'
and the text shown in 'pop-up-mini-frame' exceeds the width of
the selected window, rehost 'pop-up-mini-frame' to the selected
frame's main window."
  :type 'boolean
  :initialize 'custom-initialize-default
  :set 'pop-up-mini--set-value
  :version "27.1"
  :group 'pop-up-mini)

(defcustom pop-up-mini-hide-if-empty 0.5
  "If non-nil, delay for hiding the empty 'pop-up-mini-frame'.
If this is nil, never hide the 'pop-up-mini-frame'.  Otherwise,
it specifies the number of seconds to wait before hiding an empty
'pop-up-mini-frame'.  Zero means to hide 'pop-up-mini-frame'
immediately after it becomes empty."
  :type '(choice (const nil)
		 (number :tag "delay"))
  :initialize 'custom-initialize-default
  :set 'pop-up-mini--set-value
  :version "27.1"
  :group 'pop-up-mini)

(defcustom pop-up-mini-position 'scroll-bar
  "Position of 'pop-up-mini-frame' within its host window.
Choices are

'body-bottom' - at the bottom of the host's body if the host is a
   live window, at the bottom of the host window otherwise.  For
   a live host window this avoids covering the window's mode line
   and any scroll bars, fringes, or margins.

'body-top' - at the top of the host window's body if the host is
   a live window, at the top of the host window otherwise.  For a
   live host window this avoids covering the window's header line
   and any scroll bars, fringes, or margins.

'scroll-bar' - above the mode line of the host window if it is
   live, at the bottom of the host window otherwise.  This will
   usually hide the horizontal scroll bar of the host window.

'bottom' - at the bottom of the host window.  This will usually
   cover the host window's mode line, if any.

'top' - at the top of the host window.  This will usually cover
   the host window's header line, if any.

The width of 'pop-up-mini-frame' is the body width of the host
window for the first two options and the total width of the host
window for the remaining ones."
  :type '(choice (const body-bottom)
                 (const body-top)
		 (const scroll-bar)
                 (const bottom)
                 (const top))
  :initialize 'custom-initialize-default
  :set 'pop-up-mini--set-value
  :version "27.1"
  :group 'pop-up-mini)

(defcustom pop-up-mini-resize-manually t
  "If non-nil, allow manually resizing of 'pop-up-mini-frame'.
This allows to temporarily drag the upper border of the selected
'pop-up-mini-frame' with the mouse until it shrinks back to one
line or becomes empty."
  :type 'boolean
  :initialize 'custom-initialize-default
  :set 'pop-up-mini--set-value
  :version "27.1"
  :group 'pop-up-mini)

(defcustom pop-up-mini-internal-border "blue"
  "Background of internal border of 'pop-up-mini-frame'."
  :type 'string
  :set 'pop-up-mini--set-value
  :version "27.1"
  :group 'pop-up-mini)

(defvar pop-up-mini-buffer nil
  "Present or past buffer of 'pop-up-mini-window'.
This is the buffer shown in 'pop-up-mini-window' the last time
'resize-mini-frame' was called for its frame.")

(defvar pop-up-mini-text ""
  "Text displayed in 'pop-up-mini-window'.")

(defvar pop-up-mini-text-pixel-size '(0 . 0)
  "Size of 'pop-up-mini-text' the last time it was calculated.
The return value of 'window-text-pixel-size' the last time it was
run for 'pop-up-mini-window'.  The X-LIMIT for that run was the
width of the parent frame of 'pop-up-mini-frame' at that time.
The buffer text of 'pop-up-mini-window' at that time was
'pop-up-mini-text'.")

(defvar pop-up-mini-window-pixel-width 0
  "Pixel width of 'pop-up-mini-window'.")

(defvar pop-up-mini-window-pixel-height 0
  "Pixel height of 'pop-up-mini-window'.")

(defvar pop-up-mini-block-height nil
  "Non-nil means temporarily block height adjustment.")

(defvar pop-up-mini-hide-if-empty-timer nil
  "Timer for hiding 'pop-up-mini-frame'.")

(defun pop-up-mini-host-window (&optional frame)
  "Return window to host 'pop-up-mini-frame' on FRAME.
FRAME defaults to the selected frame."
  (cond
   ((eq pop-up-mini-host 'main)
    (window-main-window frame))
   ((eq pop-up-mini-host 'root)
    (frame-root-window frame))
   (t
    (frame-selected-window frame))))

(defun pop-up-mini-hide ()
  "Hide pop-up-mini-frame."
  (when (frame-live-p pop-up-mini-frame)
    (make-frame-invisible pop-up-mini-frame)
    (when (timerp pop-up-mini-hide-if-empty-timer)
      (cancel-timer pop-up-mini-hide-if-empty-timer)
      (setq pop-up-mini-hide-if-empty-timer nil))))

(defun pop-up-mini-move (frame &optional hide-immediately)
  "Maybe move and resize 'pop-up-mini-frame' to FRAME."
  (let* ((host (pop-up-mini-host-window frame))
	 (position pop-up-mini-position)
	 (body (and (window-live-p host)
		    (memq position '(body-bottom body-top))))
	 (edges (window-edges host body nil t))
	 (borders-width
	  (* (frame-parameter pop-up-mini-frame 'internal-border-width) 2))
	 (body-width (car pop-up-mini-text-pixel-size))
	 (body-height (cdr pop-up-mini-text-pixel-size))
	 total-width total-height extended-width extended-main)

;;     (with-current-buffer (get-buffer-create "*foo*")
;;       (goto-char (point-max))
;;       (insert (format "%s\n" hide-immediately)))

    (if (and (numberp pop-up-mini-hide-if-empty)
	     (zerop body-width) (zerop body-height))
	(cond
	 ((or hide-immediately (<= pop-up-mini-hide-if-empty 0))
	  ;; An empty 'pop-up-mini-buffer' - hide it.
	  (setq pop-up-mini-block-height nil)
	  (make-frame-invisible pop-up-mini-frame))
	 (t
	  (setq pop-up-mini-block-height nil)
	  (setq pop-up-mini-hide-if-empty-timer
		(run-with-timer
		 pop-up-mini-hide-if-empty nil 'pop-up-mini-hide))))
      ;; If 'pop-up-mini-resize-manually' is non-nil keep around host
      ;; and height of a manually resized 'pop-up-mini-frame' as long
      ;; as it's larger than one line and its buffer is non-empty.
      (if pop-up-mini-block-height
	  (setq pop-up-mini-block-height
	      (and (not (zerop body-width))
		   (not (zerop body-height))
		   (> (window-pixel-height pop-up-mini-window)
		      (frame-char-height pop-up-mini-frame))))
	(setq pop-up-mini-block-height
	      (and pop-up-mini-resize-manually
		   (eq pop-up-mini-frame (selected-frame))
		   (/= (window-pixel-height pop-up-mini-window)
		       (window-old-pixel-height pop-up-mini-window)))))

;;       (with-current-buffer (get-buffer-create "*foo*")
;; 	(goto-char (point-max))
;; 	(insert (format "foobar %s .. %s .. %s\n"
;; 			pop-up-mini-hide-if-empty
;; 			body-width body-height)))

      ;; Check minimum width and height of selected window.
      (cond
       ;; For 'scroll-bar' detract mode line and divider height from
       ;; third edge.
       ((and (eq position 'scroll-bar) (eq pop-up-mini-host 'selected))
	(setq edges (list (nth 0 edges) (nth 1 edges) (nth 2 edges)
			  (- (nth 3 edges) (window-mode-line-height host)
			     (window-bottom-divider-width host))))
	(setq position 'bottom))
       ;; For 'bottom' detract divider height from third edge when host
       ;; is live ('main' slightly loses here).
       ((and (eq position 'bottom) (window-live-p host))
	(setq edges (list (nth 0 edges) (nth 1 edges) (nth 2 edges)
			  (- (nth 3 edges)
			     (window-bottom-divider-width host))))))
      (setq total-width
	    (+ body-width
	       (- (window-pixel-width pop-up-mini-window)
		  (window-body-width pop-up-mini-window t))
	       borders-width))

      (unless pop-up-mini-block-height
	(setq total-height
	      (+ body-height
		 (- (window-pixel-height pop-up-mini-window)
		    (window-body-height pop-up-mini-window t))
		 borders-width)))

      ;; Extend on scroll bars, maybe.
      (when (and (eq pop-up-mini-position 'scroll-bar)
		 (window-combined-p nil t)
		 (or (< (- (nth 2 edges) (nth 0 edges)
			   (window-right-divider-width host))
			total-width)
		     (< (- (nth 2 edges) (nth 0 edges)
			   (window-right-divider-width host))
			pop-up-mini-host-min-width)))
	(let* ((edge-0 (nth 0 edges))
	       (sibling (window-next-sibling))
	       (edge-2 (nth 2 (window-edges sibling nil nil t)))
	       (width (- edge-2 edge-0)))
	  (while (and sibling (< width total-width))
	    (setq sibling (window-next-sibling sibling))
	    (setq edge-2 (nth 2 (window-edges sibling nil nil t)))
	    (setq width (- edge-2 edge-0)))
	  (if (>= width total-width)
	      (progn
		(setq extended-width width)
		(setq extended-main
		      (and sibling (not (window-live-p sibling)))))
	    (setq edge-2 (nth 2 (window-edges
				 (window-main-window frame) nil nil t)))
	    (setq width (- edge-2 edge-0))
	    (when (>= width total-width)
	      (setq extended-main t)
	      (setq extended-width width)))))

      (when (and (not pop-up-mini-block-height)
		 (eq pop-up-mini-host 'selected)
		 (not extended-width)
		 (or (not (zerop pop-up-mini-host-min-width))
		     (not (zerop pop-up-mini-host-min-height))
		     pop-up-mini-rehost-to-fit)
		 (or (and (/= (window-total-width host)
			      (window-total-width (window-main-window frame)))
			  (or (< (- (nth 2 edges) (nth 0 edges)
				    (window-right-divider-width host))
				 total-width)
			      (< (- (nth 2 edges) (nth 0 edges)
				    (window-right-divider-width host))
				 pop-up-mini-host-min-width)
		     (and (/= (window-total-height host)
			      (window-total-height (window-main-window frame)))
			  (or (< (- (nth 3 edges) (nth 1 edges)) total-height)
			      (< (- (nth 3 edges) (nth 1 edges))
				 pop-up-mini-host-min-height)))))))
	;; FRAME's selected window is too small, use its main window.
	(setq host (window-main-window frame))
	(setq position
	      (cond
	       ((eq position 'body-top) 'top)
	       ((eq position 'body-bottom) 'bottom)
	       (t position)))
	(setq edges (window-edges host nil nil t)))

;;       (with-current-buffer (get-buffer-create "*foo*")
;; 	(goto-char (point-max))
;; 	(insert (format "bar %s .. %s .. %s .. host: %s .. %s >= %s\n"
;; 			pop-up-mini-buffer pop-up-mini-text
;; 			pop-up-mini-text-pixel-size
;; 			host (- (nth 2 edges) (nth 0 edges)) body-width)))

;;       (with-current-buffer (get-buffer-create "*foo*")
;; 	(goto-char (point-max))
;; 	(insert (format "bar top: %s ... height: %s\n"
;; 			(- (frame-pixel-height frame) (nth 3 edges))
;; 			total-height)))

      ;; Cancel our timer.
      (when (timerp pop-up-mini-hide-if-empty-timer)
	(cancel-timer pop-up-mini-hide-if-empty-timer)
	(setq pop-up-mini-hide-if-empty-timer nil))
      ;; Resize and position.
      (modify-frame-parameters
       pop-up-mini-frame
       `((parent-frame . ,frame)
	 (visibility . t)
	 (top . ,(if (memq pop-up-mini-position '(top body-top))
		     (nth 1 edges)
		   `(- ,(- (frame-pixel-height frame) (nth 3 edges)))))
	 (left . ,(nth 0 edges))
	 ,(unless pop-up-mini-block-height
	    `(height . ,(cons 'text-pixels
			      ;; Don't make 'pop-up-mini-frame' higher
			      ;; than its host window.
			      (min (- (nth 3 edges) (nth 1 edges))
				   total-height))))
	 (width . ,(cons 'text-pixels
			 ;; Make 'pop-up-mini-frame' as wide as its
			 ;; host window.
			 (or (and extended-width
				  (- extended-width
				     (if (and (window-live-p host) (not extended-main))
					 (window-right-divider-width host)
				       0)
				     (- (window-pixel-width pop-up-mini-window)
					(window-body-width pop-up-mini-window t))
				     borders-width))
			     (- (nth 2 edges) (nth 0 edges)
				(if (window-live-p host)
				    (window-right-divider-width host)
				  0)
				(- (window-pixel-width pop-up-mini-window)
				   (window-body-width pop-up-mini-window t))
				borders-width))))))
      (setq pop-up-mini-window-pixel-width
	    (window-pixel-width pop-up-mini-window))
      (setq pop-up-mini-window-pixel-height
	    (window-pixel-height pop-up-mini-window)))))

(defun pop-up-mini-window-state-change ()
  "'pop-up-mini-mode' function run by 'window-state-change-hook'.
If the selected window, the window specfied by 'pop-up-mini-host'
or 'pop-up-mini-text' changed since last redisplay, reparent,
resize and/or reposition 'pop-up-mini-frame' if necessary."
  (when (frame-live-p pop-up-mini-frame)
    (let* ((old-parent
	    (and (frame-live-p (frame-parent pop-up-mini-frame))
		 (frame-parent pop-up-mini-frame)))
	   (new-parent
	    (cond
	     ((eq (selected-frame) old-parent) old-parent)
	     ((eq (selected-frame) pop-up-mini-frame)
	      (if (minibuffer-selected-window)
		  (let ((frame (window-frame (minibuffer-selected-window))))
		    (if (and (not (eq frame old-parent))
			     (eq (minibuffer-window frame) pop-up-mini-window))
			;; Special case where selected window changed
			;; _and_ 'pop-up-mini-window' got selected.
			frame
		      old-parent))))
	     ((eq (minibuffer-window) pop-up-mini-window) (selected-frame))
	     (t old-parent)))
	   hide-immediately)

;;       (unless (eq (frame-old-selected-window new-parent)
;; 		  (frame-selected-window new-parent))
;; 	(with-current-buffer (get-buffer-create "*foo*")
;; 	  (goto-char (point-max))
;; 	  (insert (format "%s ... %s\n"
;; 			  (frame-old-selected-window new-parent)
;; 			  (frame-selected-window new-parent)))))

      (when (and (frame-live-p new-parent)
		 (or (setq hide-immediately (not (eq old-parent new-parent)))
		     (let ((host-window (pop-up-mini-host-window new-parent)))
		       (setq hide-immediately
			     (or (and (eq pop-up-mini-host 'selected)
				      (not (eq (frame-old-selected-window
						new-parent)
					       (frame-selected-window
						new-parent))))
				 (/= (window-pixel-height host-window)
				     (window-old-pixel-height host-window))
				 (/= (window-pixel-width host-window)
				     (window-old-pixel-width host-window)))))
		     (frame-window-state-change pop-up-mini-frame)))
	;; Something really changed, dig further.
	(pop-up-mini-move new-parent hide-immediately)))))

(defun pop-up-mini-resize-mini-frame (frame)
  "'resize-mini-frames' function of 'pop-up-mini-mode'."
  (when (eq frame pop-up-mini-frame)
    (let* ((buffer (window-buffer pop-up-mini-window))
	   (text (with-current-buffer buffer
		   ;; Since we ignore text properties we will miss the
		   ;; case of displaying the same string with
		   ;; different text properties twice in a row.
		   (buffer-substring-no-properties (point-min) (point-max)))))
      ;; Return when there's no change.  This means that
      ;; 'pop-up-mini-buffer', 'pop-up-mini-text' as well as width and
      ;; height of 'pop-up-mini-window' are the same as the last time
      ;; we displayed them.
      (unless (and (eq buffer pop-up-mini-buffer)
		   (string-equal pop-up-mini-text text)
		   ;; Make sure that we do not miss a case where we
		   ;; want to make 'pop-up-mini-frame' invisible.
		   (or (not pop-up-mini-hide-if-empty)
		       (not (string-equal text ""))
		       (not (frame-visible-p pop-up-mini-frame)))
		   (equal (window-pixel-width pop-up-mini-window)
			  pop-up-mini-window-pixel-width)
		   (equal (window-pixel-height pop-up-mini-window)
			  pop-up-mini-window-pixel-height))
	;; Remember old string.
	(setq pop-up-mini-buffer buffer)
	(setq pop-up-mini-text text)
	(setq pop-up-mini-window-pixel-width
	      (window-pixel-width pop-up-mini-window))
	(setq pop-up-mini-window-pixel-height
	      (window-pixel-height pop-up-mini-window))
	;; This is the only place where we can calculate the size.
	(setq pop-up-mini-text-pixel-size
	      (and (buffer-live-p buffer)
		   (window-text-pixel-size
		    pop-up-mini-window
		    nil nil (frame-text-width
			     (frame-parent pop-up-mini-frame)))))

;; 	(when (buffer-live-p buffer)
;; 	  (with-current-buffer (get-buffer-create "*foo*")
;; 	    (goto-char (point-max))
;; 	    (insert (format "foo %s (%s) .. %s (%s) .. %s .. %s\n"
;; 			    buffer (eq buffer pop-up-mini-buffer)
;; 			    text (string-equal text pop-up-mini-text)
;; 			    pop-up-mini-text-pixel-size
;; 			    (frame-text-width
;; 			     (frame-parent pop-up-mini-frame))))))

	;; Notify ourselves of change.
	(set-frame-window-state-change frame t)))))

(defun pop-up-mini-after-make-frame (frame)
  "Maybe make FRAME client of 'pop-up-mini-frame'."
  (when (and (not (frame-parameter frame 'minibuffer))
	     (window-live-p pop-up-mini-window))
    (set-frame-parameter frame 'minibuffer pop-up-mini-window)))

(defun pop-up-mini-setup ()
  "Set up minibuffer child frame mode.
This function makes the first minibuffer-only frame it finds the
'pop-up-mini-frame'.  Needs a minibuffer-only frame."
  (setq pop-up-mini-frame nil)

  ;; Make 'pop-up-mini-frame' the first 'minibuffer-only' frame found
  ;; on 'frame-list'.  Throw an error if we don't find one.
  (unless (catch 'found
	    (dolist (frame (frame-list))
	      (when (eq (frame-parameter frame 'minibuffer) 'only)
		(throw 'found (setq pop-up-mini-frame frame)))))
    (error "'pop-up-mini-mode' needs a minibuffer-only frame"))

  ;; The following will fail whenever someone resets the
  ;; 'unsplittable' parameter of 'pop-up-mini-frame'.
  (setq pop-up-mini-window (frame-root-window pop-up-mini-frame))
  (setq pop-up-mini-buffer (window-buffer pop-up-mini-window))
  (set-face-background
   'internal-border pop-up-mini-internal-border pop-up-mini-frame)
  ;; Usurpate 'resize-mini-frames'.  On exit reset that to nil.
  (setq resize-mini-frames 'pop-up-mini-resize-mini-frame)
  (add-hook
   'window-state-change-hook 'pop-up-mini-window-state-change)
  (add-hook
   'after-make-frame-functions 'pop-up-mini-after-make-frame))

;;;###autoload
(define-minor-mode pop-up-mini-mode
  "Show minibuffer and echo area in a child frame.
'pop-up-mini-mode' uses a child frame called 'pop-up-mini-frame'
for displaying the minibuffer or the echo area.  The parent frame
of 'pop-up-mini-frame' is the currently selected frame.  Within
its parent, 'pop-up-mini-frame' can be hosted at that frame's
selected, main or root window (see 'pop-up-mini-host') either at
that window's top or bottom (see 'pop-up-mini-position').  A
'pop-up-mini-frame' that does not display any text can be hidden
using the option 'pop-up-mini-hide-if-empty'."
  :global t
  :group 'pop-up-mini
  :init-value nil
  :link '(emacs-commentary-link "pop-up-mini.el")
  (if pop-up-mini-mode
      (if frame-initial-frame
	  ;; When the initial frame is still around wait until
	  ;; 'window-setup-hook' is run.
	  (add-hook 'window-setup-hook 'pop-up-mini-setup)
	;; Otherwise run immediately.
	(pop-up-mini-setup))
    ;; Cancel our timer.
    (when (timerp pop-up-mini-hide-if-empty-timer)
      (cancel-timer pop-up-mini-hide-if-empty-timer)
      (setq pop-up-mini-hide-if-empty-timer nil))
    (remove-hook
     'window-state-change-hook 'pop-up-mini-window-state-change)
    (remove-hook
     'after-make-frame-functions 'pop-up-mini-after-make-frame)
    ;; This is not very nice but any previous value might be broken.
    (setq resize-mini-frames nil)
    ;; Reset our variables.
    (setq pop-up-mini-window nil)
    (when pop-up-mini-frame
      ;; Unparent our frame and make it visible.
      (modify-frame-parameters
       pop-up-mini-frame
       `((parent-frame . nil) (visibility . t)))
      (setq pop-up-mini-frame nil))))

(provide 'pop-up-mini)

;;; Recommended variable settings for .emacs init file.

;; (custom-set-variables
;;  ;; Enable ourselves.
;;  '(pop-up-mini-mode 1)
;;  ;; Resize frames exactly.
;;  '(frame-resize-pixelwise t)
;;  ;; At least two lines scroll margin for selected window host.
;;  '(scroll-margin 2)
;;  ;; Automatically create a minibuffer child frame at startup and
;;  ;; reparent it immediately.
;;  '(initial-frame-alist
;;     (cons '(minibuffer . child-frame) initial-frame-alist))
;;  ;; Reuse minibuffer child frame when making a new frame.  Do not use
;;  ;; '(minibuffer . child-frame) here, it would make a new child frame.
;;  '(default-frame-alist
;;     (cons '(minibuffer . nil) default-frame-alist))
;;  '(minibuffer-frame-alist
;;    '(;; Initial positioning and sizing for the window manager.
;;      (height . 1)
;;      (width . 1.0)
;;      (top . 1.0)
;;      ;; Always show at least one line.
;;      (min-height . 1)
;;      ;; No horizontal scroll bars (they don't work properly in
;;      ;; minibuffer windows).
;;      (horizontal-scroll-bars . nil)
;;      ;; No title bar.
;;      (undecorated . t)
;;      ;; To drag the child frame's top with the mouse.
;;      (internal-border-width . 1)
;;      (drag-internal-border . t)
;;      ;; No special glyphs.
;;      (no-special-glyphs . t)
;;      ;; No foucs when child frame is (re-)mapped.
;;      (no-focus-on-map . t))))

;;; pop-up-mini.el ends here

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2019-04-23  8:46 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-11-25 11:43 bug#33498: 26.1; Unable to delete minibuffer-only+child frames Andreas Politz
2018-11-25 17:40 ` martin rudalics
2018-11-25 18:28   ` Andreas Politz
2018-11-25 18:57     ` martin rudalics
2018-11-25 19:33       ` Andreas Politz
2018-11-26  9:31         ` martin rudalics
2018-11-26 18:59           ` Andreas Politz
2018-11-27 10:14             ` martin rudalics
2019-03-05 10:12 ` martin rudalics
2019-03-13 20:24   ` Andreas Politz
2019-04-23  8:46     ` martin rudalics
2019-03-06 19:07 ` Paul Eggert
2019-03-07  8:28   ` martin rudalics

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).