aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Rudalics2025-01-14 09:51:17 +0100
committerMartin Rudalics2025-01-14 09:51:17 +0100
commitd4aeb6bd230c42cf7b773ec9aebd80ad6d928d98 (patch)
tree7ac0b80899cce5c4086c815db3008ec1e37340fd /src
parent0226d3579461c57513cb0a600eda1f6fb17f8d22 (diff)
downloademacs-d4aeb6bd230c42cf7b773ec9aebd80ad6d928d98.tar.gz
emacs-d4aeb6bd230c42cf7b773ec9aebd80ad6d928d98.zip
Handle removal of selected tty child frame
* src/dispextern.h (root_frame): * src/frame.h (root_frame): Move declaration from dispextern.h to frame.h. (SET_FRAME_VISIBLE): Whend making the selected tty child frame invisible, use mru_rooted_frame to find a frame to switch to. * src/dispnew.c (root_frame): Move root_frame to frame.c. * src/frame.c (do_switch_frame): On ttys don't change the top frame when switching from a child frame to another frame with the same root. (root_frame): Move here from dispnew.c. (Fframe_root_frame): New Lisp function. (delete_frame): Whend deleting the selected tty child frame use, mru_rooted_frame to find a frame to switch to. * src/window.c (mru_rooted_frame): New function. * src/window.h (mru_rooted_frame): Declare it. * doc/lispref/frames.texi (Child Frames): Describe new function 'frame-root-frame'.
Diffstat (limited to 'src')
-rw-r--r--src/dispextern.h1
-rw-r--r--src/dispnew.c12
-rw-r--r--src/frame.c131
-rw-r--r--src/frame.h39
-rw-r--r--src/window.c32
-rw-r--r--src/window.h1
6 files changed, 141 insertions, 75 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index e3e621e7318..1d90022a9bc 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3949,7 +3949,6 @@ extern void gui_redo_mouse_highlight (Display_Info *);
3949 3949
3950#endif /* HAVE_WINDOW_SYSTEM */ 3950#endif /* HAVE_WINDOW_SYSTEM */
3951 3951
3952struct frame *root_frame (struct frame *f);
3953Lisp_Object frames_in_reverse_z_order (struct frame *f, bool visible); 3952Lisp_Object frames_in_reverse_z_order (struct frame *f, bool visible);
3954bool is_tty_frame (struct frame *f); 3953bool is_tty_frame (struct frame *f);
3955bool is_tty_child_frame (struct frame *f); 3954bool is_tty_child_frame (struct frame *f);
diff --git a/src/dispnew.c b/src/dispnew.c
index 5bc6958622d..cb57edcec0f 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3334,18 +3334,6 @@ frame_rect_abs (struct frame *f)
3334 3334
3335#endif /* !HAVE_ANDROID */ 3335#endif /* !HAVE_ANDROID */
3336 3336
3337/* Return the root frame of frame F. Follow the parent_frame chain
3338 until we reach a frame that has no parent. That is the root frame.
3339 Note that the root of a root frame is itself. */
3340
3341struct frame *
3342root_frame (struct frame *f)
3343{
3344 while (FRAME_PARENT_FRAME (f))
3345 f = FRAME_PARENT_FRAME (f);
3346 return f;
3347}
3348
3349int 3337int
3350max_child_z_order (struct frame *parent) 3338max_child_z_order (struct frame *parent)
3351{ 3339{
diff --git a/src/frame.c b/src/frame.c
index 212331c0b3a..4559bc41ab8 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1775,7 +1775,7 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1775 1775
1776 /* Don't mark the frame garbaged if we are switching to the frame 1776 /* Don't mark the frame garbaged if we are switching to the frame
1777 that is already the top frame of that TTY. */ 1777 that is already the top frame of that TTY. */
1778 if (!EQ (frame, top_frame)) 1778 if (!EQ (frame, top_frame) && root_frame (f) != XFRAME (top_frame))
1779 { 1779 {
1780 struct frame *new_root = root_frame (f); 1780 struct frame *new_root = root_frame (f);
1781 SET_FRAME_VISIBLE (new_root, true); 1781 SET_FRAME_VISIBLE (new_root, true);
@@ -2021,6 +2021,39 @@ frame. */)
2021 return frame_ancestor_p (af, df) ? Qt : Qnil; 2021 return frame_ancestor_p (af, df) ? Qt : Qnil;
2022} 2022}
2023 2023
2024
2025/* Return the root frame of frame F. Follow the parent_frame chain
2026 until we reach a frame that has no parent. That is the root frame.
2027 Note that the root of a root frame is itself. */
2028
2029struct frame *
2030root_frame (struct frame *f)
2031{
2032 while (FRAME_PARENT_FRAME (f))
2033 f = FRAME_PARENT_FRAME (f);
2034 return f;
2035}
2036
2037
2038DEFUN ("frame-root-frame", Fframe_root_frame, Sframe_root_frame,
2039 0, 1, 0,
2040 doc: /* Return root frame of specified FRAME.
2041FRAME must be a live frame and defaults to the selected one. The root
2042frame of FRAME is the frame obtained by following the chain of parent
2043frames starting with FRAME until a frame is reached that has no parent.
2044If FRAME has no parent, its root frame is FRAME. */)
2045 (Lisp_Object frame)
2046{
2047 struct frame *f = decode_live_frame (frame);
2048 struct frame *r = root_frame (f);
2049 Lisp_Object root;
2050
2051 XSETFRAME (root, r);
2052
2053 return root;
2054}
2055
2056
2024/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the 2057/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
2025 same tty (for tty frames) or among frames which uses FRAME's keyboard. 2058 same tty (for tty frames) or among frames which uses FRAME's keyboard.
2026 If MINIBUF is nil, do not consider minibuffer-only candidate. 2059 If MINIBUF is nil, do not consider minibuffer-only candidate.
@@ -2433,61 +2466,68 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2433 /* Don't let the frame remain selected. */ 2466 /* Don't let the frame remain selected. */
2434 if (f == sf) 2467 if (f == sf)
2435 { 2468 {
2436 Lisp_Object tail; 2469 if (is_tty_child_frame (f))
2437 Lisp_Object frame1 UNINIT; /* This line works around GCC bug 85563. */ 2470 /* If F is a child frame on a tty and is the selected frame, try
2438 eassume (CONSP (Vframe_list)); 2471 to re-select the frame that was selected before F. */
2439 2472 do_switch_frame (mru_rooted_frame (f), 0, 1, Qnil);
2440 /* Look for another visible frame on the same terminal. 2473 else
2441 Do not call next_frame here because it may loop forever.
2442 See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025. */
2443 FOR_EACH_FRAME (tail, frame1)
2444 { 2474 {
2445 struct frame *f1 = XFRAME (frame1); 2475 Lisp_Object tail;
2446 2476 Lisp_Object frame1 UNINIT; /* This line works around GCC bug 85563. */
2447 if (!EQ (frame, frame1) 2477 eassume (CONSP (Vframe_list));
2448 && !FRAME_TOOLTIP_P (f1)
2449 && FRAME_TERMINAL (f) == FRAME_TERMINAL (f1)
2450 && FRAME_VISIBLE_P (f1))
2451 break;
2452 }
2453 2478
2454 /* If there is none, find *some* other frame. */ 2479 /* Look for another visible frame on the same terminal.
2455 if (NILP (frame1) || EQ (frame1, frame)) 2480 Do not call next_frame here because it may loop forever.
2456 { 2481 See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025. */
2457 FOR_EACH_FRAME (tail, frame1) 2482 FOR_EACH_FRAME (tail, frame1)
2458 { 2483 {
2459 struct frame *f1 = XFRAME (frame1); 2484 struct frame *f1 = XFRAME (frame1);
2460 2485
2461 if (!EQ (frame, frame1) 2486 if (!EQ (frame, frame1)
2462 && FRAME_LIVE_P (f1) 2487 && !FRAME_TOOLTIP_P (f1)
2463 && !FRAME_TOOLTIP_P (f1)) 2488 && FRAME_TERMINAL (f) == FRAME_TERMINAL (f1)
2489 && FRAME_VISIBLE_P (f1))
2490 break;
2491 }
2492
2493 /* If there is none, find *some* other frame. */
2494 if (NILP (frame1) || EQ (frame1, frame))
2495 {
2496 FOR_EACH_FRAME (tail, frame1)
2464 { 2497 {
2465 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1)) 2498 struct frame *f1 = XFRAME (frame1);
2466 {
2467 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
2468 2499
2469 if (!EQ (top_frame, frame)) 2500 if (!EQ (frame, frame1)
2470 frame1 = top_frame; 2501 && FRAME_LIVE_P (f1)
2502 && !FRAME_TOOLTIP_P (f1))
2503 {
2504 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
2505 {
2506 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
2507
2508 if (!EQ (top_frame, frame))
2509 frame1 = top_frame;
2510 }
2511 break;
2471 } 2512 }
2472 break;
2473 } 2513 }
2474 } 2514 }
2475 }
2476#ifdef NS_IMPL_COCOA 2515#ifdef NS_IMPL_COCOA
2477 else 2516 else
2478 { 2517 {
2479 /* Under NS, there is no system mechanism for choosing a new 2518 /* Under NS, there is no system mechanism for choosing a new
2480 window to get focus -- it is left to application code. 2519 window to get focus -- it is left to application code.
2481 So the portion of THIS application interfacing with NS 2520 So the portion of THIS application interfacing with NS
2482 needs to make the frame we switch to the key window. */ 2521 needs to make the frame we switch to the key window. */
2483 struct frame *f1 = XFRAME (frame1); 2522 struct frame *f1 = XFRAME (frame1);
2484 if (FRAME_NS_P (f1)) 2523 if (FRAME_NS_P (f1))
2485 ns_make_frame_key_window (f1); 2524 ns_make_frame_key_window (f1);
2486 } 2525 }
2487#endif 2526#endif
2488 2527
2489 do_switch_frame (frame1, 0, 1, Qnil); 2528 do_switch_frame (frame1, 0, 1, Qnil);
2490 sf = SELECTED_FRAME (); 2529 sf = SELECTED_FRAME ();
2530 }
2491 } 2531 }
2492 else 2532 else
2493 /* Ensure any minibuffers on FRAME are moved onto the selected 2533 /* Ensure any minibuffers on FRAME are moved onto the selected
@@ -2583,11 +2623,11 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2583 f->terminal = 0; /* Now the frame is dead. */ 2623 f->terminal = 0; /* Now the frame is dead. */
2584 unblock_input (); 2624 unblock_input ();
2585 2625
2586 /* Clear markers and overlays set by F on behalf of an input 2626 /* Clear markers and overlays set by F on behalf of an input
2587 method. */ 2627 method. */
2588#ifdef HAVE_TEXT_CONVERSION 2628#ifdef HAVE_TEXT_CONVERSION
2589 if (FRAME_WINDOW_P (f)) 2629 if (FRAME_WINDOW_P (f))
2590 reset_frame_state (f); 2630 reset_frame_state (f);
2591#endif 2631#endif
2592 2632
2593 /* If needed, delete the terminal that this frame was on. 2633 /* If needed, delete the terminal that this frame was on.
@@ -7146,6 +7186,7 @@ iconify the top level frame instead. */);
7146 defsubr (&Sframe_list); 7186 defsubr (&Sframe_list);
7147 defsubr (&Sframe_parent); 7187 defsubr (&Sframe_parent);
7148 defsubr (&Sframe_ancestor_p); 7188 defsubr (&Sframe_ancestor_p);
7189 defsubr (&Sframe_root_frame);
7149 defsubr (&Snext_frame); 7190 defsubr (&Snext_frame);
7150 defsubr (&Sprevious_frame); 7191 defsubr (&Sprevious_frame);
7151 defsubr (&Slast_nonminibuf_frame); 7192 defsubr (&Slast_nonminibuf_frame);
diff --git a/src/frame.h b/src/frame.h
index bff610472c0..fea8baa7332 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1428,23 +1428,6 @@ FRAME_PARENT_FRAME (struct frame *f)
1428/* False means there are no visible garbaged frames. */ 1428/* False means there are no visible garbaged frames. */
1429extern bool frame_garbaged; 1429extern bool frame_garbaged;
1430 1430
1431/* Set visibility of frame F.
1432 We call redisplay_other_windows to make sure the frame gets redisplayed
1433 if some changes were applied to it while it wasn't visible (and hence
1434 wasn't redisplayed). */
1435INLINE void
1436SET_FRAME_VISIBLE (struct frame *f, bool v)
1437{
1438 if (v)
1439 {
1440 if (v == 1 && f->visible != 1)
1441 redisplay_other_windows ();
1442 if (FRAME_GARBAGED_P (f))
1443 frame_garbaged = true;
1444 }
1445 f->visible = v;
1446}
1447
1448/* Set iconified status of frame F. */ 1431/* Set iconified status of frame F. */
1449INLINE void 1432INLINE void
1450SET_FRAME_ICONIFIED (struct frame *f, int i) 1433SET_FRAME_ICONIFIED (struct frame *f, int i)
@@ -1518,6 +1501,7 @@ void check_tty (struct frame *f);
1518struct frame *decode_tty_frame (Lisp_Object frame); 1501struct frame *decode_tty_frame (Lisp_Object frame);
1519extern void frame_make_pointer_invisible (struct frame *); 1502extern void frame_make_pointer_invisible (struct frame *);
1520extern void frame_make_pointer_visible (struct frame *); 1503extern void frame_make_pointer_visible (struct frame *);
1504extern struct frame *root_frame (struct frame *f);
1521extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object); 1505extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object);
1522extern bool frame_inhibit_resize (struct frame *, bool, Lisp_Object); 1506extern bool frame_inhibit_resize (struct frame *, bool, Lisp_Object);
1523extern void adjust_frame_size (struct frame *, int, int, int, bool, 1507extern void adjust_frame_size (struct frame *, int, int, int, bool,
@@ -1541,6 +1525,27 @@ extern Lisp_Object Vframe_list;
1541 ? XFRAME (selected_frame) \ 1525 ? XFRAME (selected_frame) \
1542 : (emacs_abort (), (struct frame *) 0)) 1526 : (emacs_abort (), (struct frame *) 0))
1543 1527
1528/* Set visibility of frame F.
1529 We call redisplay_other_windows to make sure the frame gets redisplayed
1530 if some changes were applied to it while it wasn't visible (and hence
1531 wasn't redisplayed). */
1532INLINE void
1533SET_FRAME_VISIBLE (struct frame *f, bool v)
1534{
1535 if (v)
1536 {
1537 if (v == 1 && f->visible != 1)
1538 redisplay_other_windows ();
1539 if (FRAME_GARBAGED_P (f))
1540 frame_garbaged = true;
1541 }
1542 /* If F is a child frame on a tty and is the selected frame, try to
1543 re-select the frame that was selected before F. */
1544 else if (is_tty_child_frame (f) && f == XFRAME (selected_frame))
1545 do_switch_frame (mru_rooted_frame (f), 0, 0, Qnil);
1546
1547 f->visible = v;
1548}
1544 1549
1545/*********************************************************************** 1550/***********************************************************************
1546 Display-related Macros 1551 Display-related Macros
diff --git a/src/window.c b/src/window.c
index ff58eb12ee0..d7e6cd00c99 100644
--- a/src/window.c
+++ b/src/window.c
@@ -3097,6 +3097,38 @@ be listed first but no error is signaled. */)
3097{ 3097{
3098 return window_list_1 (window, minibuf, all_frames); 3098 return window_list_1 (window, minibuf, all_frames);
3099} 3099}
3100
3101/** Return most recently selected frame that has the same root as a
3102 given frame. It's defined here because the static window_list_1 is
3103 here too but in fact it's only needed in the frame code. */
3104Lisp_Object
3105mru_rooted_frame (struct frame *f)
3106{
3107 Lisp_Object windows = window_list_1 (FRAME_SELECTED_WINDOW (f), Qnil, Qt);
3108 struct frame *r = root_frame (f);
3109 struct window *b = NULL;
3110
3111 for (; CONSP (windows); windows = XCDR (windows))
3112 {
3113 struct window *w = XWINDOW (XCAR (windows));
3114 struct frame *wf = WINDOW_XFRAME (w);
3115
3116 if (wf != f && root_frame (wf) == r && FRAME_VISIBLE_P (wf)
3117 && (!b || w->use_time > b->use_time))
3118 b = w;
3119 }
3120
3121 if (b)
3122 return WINDOW_FRAME (b);
3123 else
3124 {
3125 Lisp_Object root;
3126
3127 XSETFRAME (root, r);
3128
3129 return root;
3130 }
3131}
3100 3132
3101/* Look at all windows, performing an operation specified by TYPE 3133/* Look at all windows, performing an operation specified by TYPE
3102 with argument OBJ. 3134 with argument OBJ.
diff --git a/src/window.h b/src/window.h
index 39356f80df7..a48c370b198 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1227,6 +1227,7 @@ extern void wset_buffer (struct window *, Lisp_Object);
1227extern bool window_outdated (struct window *); 1227extern bool window_outdated (struct window *);
1228extern ptrdiff_t window_point (struct window *w); 1228extern ptrdiff_t window_point (struct window *w);
1229extern void window_discard_buffer_from_dead_windows (Lisp_Object); 1229extern void window_discard_buffer_from_dead_windows (Lisp_Object);
1230extern Lisp_Object mru_rooted_frame (struct frame *);
1230extern void init_window_once (void); 1231extern void init_window_once (void);
1231extern void init_window (void); 1232extern void init_window (void);
1232extern void syms_of_window (void); 1233extern void syms_of_window (void);