aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Rudalics2019-03-05 10:46:19 +0100
committerMartin Rudalics2019-03-05 10:46:19 +0100
commita552cc21dc324b1be71c181684b0ab2e6cf0a60f (patch)
tree64ba993180246d1837d5a1ef3c30c1c8ed749ac2 /src
parenteb8dbafff11fded9c96294a0680455bcde70882c (diff)
downloademacs-a552cc21dc324b1be71c181684b0ab2e6cf0a60f.tar.gz
emacs-a552cc21dc324b1be71c181684b0ab2e6cf0a60f.zip
Fix handling of minibuffer-only child frames (Bug#33498)
* doc/lispref/frames.texi (Buffer Parameters): Describe how to make a minibuffer-only child frame. (Child Frames): Describe how minbuffer child frames are deleted. * src/frame.c (delete_frame): Handle deletion of minibuffer child frames (Bug#33498). In the course, fix reassigning of 'default-minibuffer-frame' with minibuffer-only frames. * lisp/frame.el (frame-notice-user-settings): Handle creation of initial minibuffer-only child frame. (make-frame): Handle creation of frame with a minibuffer-only child frame.
Diffstat (limited to 'src')
-rw-r--r--src/frame.c99
1 files changed, 84 insertions, 15 deletions
diff --git a/src/frame.c b/src/frame.c
index 165ed4a4e52..3d83dc0a0d8 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1849,6 +1849,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1849 Lisp_Object frames, frame1; 1849 Lisp_Object frames, frame1;
1850 int minibuffer_selected, is_tooltip_frame; 1850 int minibuffer_selected, is_tooltip_frame;
1851 bool nochild = !FRAME_PARENT_FRAME (f); 1851 bool nochild = !FRAME_PARENT_FRAME (f);
1852 Lisp_Object minibuffer_child_frame = Qnil;
1852 1853
1853 if (!FRAME_LIVE_P (f)) 1854 if (!FRAME_LIVE_P (f))
1854 return Qnil; 1855 return Qnil;
@@ -1865,13 +1866,33 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1865 /* Softly delete all frames with this frame as their parent frame or 1866 /* Softly delete all frames with this frame as their parent frame or
1866 as their `delete-before' frame parameter value. */ 1867 as their `delete-before' frame parameter value. */
1867 FOR_EACH_FRAME (frames, frame1) 1868 FOR_EACH_FRAME (frames, frame1)
1868 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f 1869 {
1870 struct frame *f1 = XFRAME (frame1);
1871
1872 if (EQ (frame1, frame) || FRAME_TOOLTIP_P (f1))
1873 continue;
1874 else if (FRAME_PARENT_FRAME (f1) == f)
1875 {
1876 if (FRAME_HAS_MINIBUF_P (f1) && !FRAME_HAS_MINIBUF_P (f)
1877 && EQ (FRAME_MINIBUF_WINDOW (f), FRAME_MINIBUF_WINDOW (f1)))
1878 /* frame1 owns frame's minibuffer window so we must not
1879 delete it here to avoid a surrogate minibuffer error.
1880 Unparent frame1 and make it a top-level frame. */
1881 {
1882 Fmodify_frame_parameters
1883 (frame1, Fcons (Fcons (Qparent_frame, Qnil), Qnil));
1884 minibuffer_child_frame = frame1;
1885 }
1886 else
1887 delete_frame (frame1, Qnil);
1888 }
1889 else if (nochild
1890 && EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame))
1869 /* Process `delete-before' parameter iff FRAME is not a child 1891 /* Process `delete-before' parameter iff FRAME is not a child
1870 frame. This avoids that we enter an infinite chain of mixed 1892 frame. This avoids that we enter an infinite chain of mixed
1871 dependencies. */ 1893 dependencies. */
1872 || (nochild 1894 delete_frame (frame1, Qnil);
1873 && EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame))) 1895 }
1874 delete_frame (frame1, Qnil);
1875 1896
1876 /* Does this frame have a minibuffer, and is it the surrogate 1897 /* Does this frame have a minibuffer, and is it the surrogate
1877 minibuffer for any other frame? */ 1898 minibuffer for any other frame? */
@@ -2136,18 +2157,27 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2136 { 2157 {
2137 struct frame *f1 = XFRAME (frame1); 2158 struct frame *f1 = XFRAME (frame1);
2138 2159
2139 /* Consider only frames on the same kboard 2160 /* Set frame_on_same_kboard to frame1 if it is on the same
2140 and only those with minibuffers. */ 2161 keyboard. Set frame_with_minibuf to frame1 if it also
2141 if (kb == FRAME_KBOARD (f1) 2162 has a minibuffer. Leave the loop immediately if frame1
2142 && FRAME_HAS_MINIBUF_P (f1)) 2163 is also minibuffer-only.
2164
2165 Emacs 26 does _not_ set frame_on_same_kboard here when it
2166 finds a minibuffer-only frame and subsequently fails to
2167 set default_minibuffer_frame below. Not a great deal and
2168 never noticed since make_frame_without_minibuffer creates
2169 a new minibuffer frame in that case (which can be a minor
2170 annoyance though). To consider for Emacs 26.3. */
2171 if (kb == FRAME_KBOARD (f1))
2143 { 2172 {
2144 frame_with_minibuf = frame1; 2173 frame_on_same_kboard = frame1;
2145 if (FRAME_MINIBUF_ONLY_P (f1)) 2174 if (FRAME_HAS_MINIBUF_P (f1))
2146 break; 2175 {
2176 frame_with_minibuf = frame1;
2177 if (FRAME_MINIBUF_ONLY_P (f1))
2178 break;
2179 }
2147 } 2180 }
2148
2149 if (kb == FRAME_KBOARD (f1))
2150 frame_on_same_kboard = frame1;
2151 } 2181 }
2152 2182
2153 if (!NILP (frame_on_same_kboard)) 2183 if (!NILP (frame_on_same_kboard))
@@ -2180,7 +2210,46 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2180 = Fcons (list3 (Qrun_hook_with_args, Qafter_delete_frame_functions, frame), 2210 = Fcons (list3 (Qrun_hook_with_args, Qafter_delete_frame_functions, frame),
2181 pending_funcalls); 2211 pending_funcalls);
2182 else 2212 else
2183 safe_call2 (Qrun_hook_with_args, Qafter_delete_frame_functions, frame); 2213 safe_call2 (Qrun_hook_with_args, Qafter_delete_frame_functions, frame);
2214
2215 if (!NILP (minibuffer_child_frame))
2216 /* If minibuffer_child_frame is non-nil, it was FRAME's minibuffer
2217 child frame. Delete it unless it's also the minibuffer frame
2218 of another frame in which case we make sure it's visible. */
2219 {
2220 struct frame *f1 = XFRAME (minibuffer_child_frame);
2221
2222 if (FRAME_LIVE_P (f1))
2223 {
2224 Lisp_Object window1 = FRAME_ROOT_WINDOW (f1);
2225 Lisp_Object frame2;
2226
2227 FOR_EACH_FRAME (frames, frame2)
2228 {
2229 struct frame *f2 = XFRAME (frame2);
2230
2231 if (EQ (frame2, minibuffer_child_frame) || FRAME_TOOLTIP_P (f2))
2232 continue;
2233 else if (EQ (FRAME_MINIBUF_WINDOW (f2), window1))
2234 {
2235 /* minibuffer_child_frame serves as minibuffer frame
2236 for at least one other frame - so make it visible
2237 and quit. */
2238 if (!FRAME_VISIBLE_P (f1) && !FRAME_ICONIFIED_P (f1))
2239 Fmake_frame_visible (frame1);
2240
2241 return Qnil;
2242 }
2243 }
2244
2245 /* No other frame found that uses minibuffer_child_frame as
2246 minibuffer frame. If FORCE is Qnoelisp or there are
2247 other visible frames left, delete minibuffer_child_frame
2248 since it presumably was used by FRAME only. */
2249 if (EQ (force, Qnoelisp) || other_frames (f1, false, !NILP (force)))
2250 delete_frame (minibuffer_child_frame, Qnoelisp);
2251 }
2252 }
2184 2253
2185 return Qnil; 2254 return Qnil;
2186} 2255}