diff options
| author | Martin Rudalics | 2025-01-14 09:51:17 +0100 |
|---|---|---|
| committer | Martin Rudalics | 2025-01-14 09:51:17 +0100 |
| commit | d4aeb6bd230c42cf7b773ec9aebd80ad6d928d98 (patch) | |
| tree | 7ac0b80899cce5c4086c815db3008ec1e37340fd /src | |
| parent | 0226d3579461c57513cb0a600eda1f6fb17f8d22 (diff) | |
| download | emacs-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.h | 1 | ||||
| -rw-r--r-- | src/dispnew.c | 12 | ||||
| -rw-r--r-- | src/frame.c | 131 | ||||
| -rw-r--r-- | src/frame.h | 39 | ||||
| -rw-r--r-- | src/window.c | 32 | ||||
| -rw-r--r-- | src/window.h | 1 |
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 | ||
| 3952 | struct frame *root_frame (struct frame *f); | ||
| 3953 | Lisp_Object frames_in_reverse_z_order (struct frame *f, bool visible); | 3952 | Lisp_Object frames_in_reverse_z_order (struct frame *f, bool visible); |
| 3954 | bool is_tty_frame (struct frame *f); | 3953 | bool is_tty_frame (struct frame *f); |
| 3955 | bool is_tty_child_frame (struct frame *f); | 3954 | bool 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 | |||
| 3341 | struct frame * | ||
| 3342 | root_frame (struct frame *f) | ||
| 3343 | { | ||
| 3344 | while (FRAME_PARENT_FRAME (f)) | ||
| 3345 | f = FRAME_PARENT_FRAME (f); | ||
| 3346 | return f; | ||
| 3347 | } | ||
| 3348 | |||
| 3349 | int | 3337 | int |
| 3350 | max_child_z_order (struct frame *parent) | 3338 | max_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 | |||
| 2029 | struct frame * | ||
| 2030 | root_frame (struct frame *f) | ||
| 2031 | { | ||
| 2032 | while (FRAME_PARENT_FRAME (f)) | ||
| 2033 | f = FRAME_PARENT_FRAME (f); | ||
| 2034 | return f; | ||
| 2035 | } | ||
| 2036 | |||
| 2037 | |||
| 2038 | DEFUN ("frame-root-frame", Fframe_root_frame, Sframe_root_frame, | ||
| 2039 | 0, 1, 0, | ||
| 2040 | doc: /* Return root frame of specified FRAME. | ||
| 2041 | FRAME must be a live frame and defaults to the selected one. The root | ||
| 2042 | frame of FRAME is the frame obtained by following the chain of parent | ||
| 2043 | frames starting with FRAME until a frame is reached that has no parent. | ||
| 2044 | If 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. */ |
| 1429 | extern bool frame_garbaged; | 1429 | extern 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). */ | ||
| 1435 | INLINE void | ||
| 1436 | SET_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. */ |
| 1449 | INLINE void | 1432 | INLINE void |
| 1450 | SET_FRAME_ICONIFIED (struct frame *f, int i) | 1433 | SET_FRAME_ICONIFIED (struct frame *f, int i) |
| @@ -1518,6 +1501,7 @@ void check_tty (struct frame *f); | |||
| 1518 | struct frame *decode_tty_frame (Lisp_Object frame); | 1501 | struct frame *decode_tty_frame (Lisp_Object frame); |
| 1519 | extern void frame_make_pointer_invisible (struct frame *); | 1502 | extern void frame_make_pointer_invisible (struct frame *); |
| 1520 | extern void frame_make_pointer_visible (struct frame *); | 1503 | extern void frame_make_pointer_visible (struct frame *); |
| 1504 | extern struct frame *root_frame (struct frame *f); | ||
| 1521 | extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object); | 1505 | extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object); |
| 1522 | extern bool frame_inhibit_resize (struct frame *, bool, Lisp_Object); | 1506 | extern bool frame_inhibit_resize (struct frame *, bool, Lisp_Object); |
| 1523 | extern void adjust_frame_size (struct frame *, int, int, int, bool, | 1507 | extern 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). */ | ||
| 1532 | INLINE void | ||
| 1533 | SET_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. */ | ||
| 3104 | Lisp_Object | ||
| 3105 | mru_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); | |||
| 1227 | extern bool window_outdated (struct window *); | 1227 | extern bool window_outdated (struct window *); |
| 1228 | extern ptrdiff_t window_point (struct window *w); | 1228 | extern ptrdiff_t window_point (struct window *w); |
| 1229 | extern void window_discard_buffer_from_dead_windows (Lisp_Object); | 1229 | extern void window_discard_buffer_from_dead_windows (Lisp_Object); |
| 1230 | extern Lisp_Object mru_rooted_frame (struct frame *); | ||
| 1230 | extern void init_window_once (void); | 1231 | extern void init_window_once (void); |
| 1231 | extern void init_window (void); | 1232 | extern void init_window (void); |
| 1232 | extern void syms_of_window (void); | 1233 | extern void syms_of_window (void); |