[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#71343: 30.0.50; TTY frame doesn't automatically redisplay itself aft
From: |
Daniel Clemente |
Subject: |
bug#71343: 30.0.50; TTY frame doesn't automatically redisplay itself after having closed another frame |
Date: |
Sun, 16 Jun 2024 05:40:12 +0000 |
I have a new discovery (it's about „initial frame“), you can skip to
the gdb info below (line 16876).
> > Random ideas, without knowing much about terminals.
> > - Can't an X terminal detect „I've been given X focus“ and pass this
> > signal to the program running inside it?
>
> You assume that it will be a terminal belonging to Emacs that will get
> focus? That is not given.
>
I was thinking that maybe X always does this (X notifies the terminal
emulator, which notifies the program running inside it, whatever
program it is).
I brainstorm ideas without X knowledge; please ignore the bad ones.
But I think „window focus“ isn't the main issue here; more on this below.
> > - What if, when closing a TTY frame in emacsclient, all other frames
> > are redisplayed
>
> Why?
This one is a bad idea, or a last resort solution, in case there's no
other way to detect that some frames (or which ones) may need to be
refreshed.
>
> > - What if, when resizing the frame (something which Emacs detects),
> > Emacs knows/detects that a frame was closed, and decides not to delay
> > the redisplay?
>
> Redisplay of which frame? Emacs only redisplays a frame if some
> change in buffer text justifies that.
I propose it should repaint/redisplay the frame whose size changed.
Maybe I'm not using the right word, „redisplay“. What I mean is that
it should refresh its contents („frame redraw“ I think it's called) to
use the new size. For instance if I make the frame wider, now there's
more space, more words fit in each line, the minibuffer needs to be
extended to the right. Even if the buffer text didn't change.
I have 2 frames, kill the 2nd one, and resize the 1st one. Right now,
Emacs is indeed running adjust_frame_size, and it decides not to
repaint the contents; instead it leaves black areas. (Just in this
case after having closed a frame). This does seem like a bug, because
any type of frame size change should trigger a refresh to use the new
size.
Don't we know which frame is the one being resized? It should be f in
adjust_frame_size. It realizes that e.g. it's being resized from 72 to
61 columns.
(gdb) info locals
w = 0x7fffffffc000
text_area_y = -16112
text_area_x = -16288
text_area_width = -16128
text_area_height = 1102416563
unit_width = 1
unit_height = 1
old_native_width = 72
old_native_height = 50
new_native_width = 61
new_native_height = 50
min_inner_width = 2
min_inner_height = 4
r = 0x62100022d130
old_inner_width = 72
old_inner_height = 49
new_inner_width = 61
new_inner_height = 49
old_text_cols = 72
old_text_lines = 49
new_text_cols = 61
new_text_lines = 49
old_text_width = 72
old_text_height = 49
inhibit_horizontal = true
inhibit_vertical = true
frame = XIL(0x621000181105)
And yet it doesn't redraw.
I'm still learning the internals to be able to understand what
happens. resize_frame_windows does its job. pool_changed_p (in
adjust_frame_glyphs_for_frame_redisplay) is true. display_completed is
true. FRAME_GARBAGED_P (f) is true. Later in do_pending_window_change
delayed_size_change is false. When later I press a key,
clear_garbaged_frames is run (invoked by redisplay_internal)
In normal conditions, resizing a frame calls: adjust_frame size, then
redisplay_internal, then clear_garbaged_frames, then redraw_frame
But when I reproduce this bug (i.e. just after closing a frame),
resizing a frame calls: adjust_frame_size, then redisplay_internal. It
doesn't call the other two.
(Only later when I press a key, it calls redisplay_internal, then
clear_garbaged_frames, then redraw_frame)
In this scenario, why doesn't redisplay_internal reach the point where
it calls clear_garbaged_frames?
Because this happens:
Breakpoint 5, redisplay_internal () at xdisp.c:16831
16831 struct window *w = XWINDOW (selected_window);
(gdb) n
16835 bool must_finish = false, match_p;
(gdb)
16839 bool polling_stopped_here = false;
(gdb)
16846 int hscroll_retries = 0;
(gdb)
16854 int garbaged_frame_retries = 0;
(gdb)
16862 bool update_miniwindow_p = false;
(gdb)
16864 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
(gdb)
16870 if (redisplaying_p)
(gdb)
16876 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
(gdb)
16877 && redisplay_skip_initial_frame)
(gdb)
16879 return;
(gdb)
So, apparently it thinks that my frame is initial.
But from a first view, that doesn't look right. The frame I'm resizing
isn't initial.
It even has a glyph matrix, 2 windows, …
If I open 4 frames, close the 4th one and resize the 3rd one, it sees
it as initial.
This part of the code is new to me. I'll research it more but I wanted
to send this information now.
I have also seen that some of my frames have f->terminal->name =
"initial_terminal", I don't know if that's related or bad.
Some more data about the looks-initial frame:
(gdb) p *SELECTED_FRAME()
$102 = {
header = {
size = 4611686018595348501
},
name = XIL(0x555557e78944),
icon_name = XIL(0),
title = XIL(0),
last_mouse_device = XIL(0),
focus_frame = XIL(0),
root_window = XIL(0x621000004125),
selected_window = XIL(0x621000004125),
old_selected_window = XIL(0x621000004125),
minibuffer_window = XIL(0x6210000043bd),
param_alist = XIL(0x7ffff18bc633),
scroll_bars = XIL(0),
condemned_scroll_bars = XIL(0),
menu_bar_items = XIL(0x6210000ca905),
face_hash_table = XIL(0x621000004655),
menu_bar_vector = XIL(0),
buffer_predicate = XIL(0),
buffer_list = XIL(0x7ffff00cbe23),
buried_buffer_list = XIL(0),
tool_bar_position = XIL(0xfab0),
tab_bar_items = XIL(0),
tool_bar_items = XIL(0),
face_cache = 0x604000000ad0,
last_tab_bar_item = 0,
menu_bar_items_used = 0,
current_pool = 0x603000002fe0,
desired_pool = 0x603000002fb0,
desired_matrix = 0x616000001280,
current_matrix = 0x616000001580,
glyphs_initialized_p = true,
resized_p = false,
default_face_done_p = false,
already_hscrolled_p = false,
updated_p = false,
fonts_changed = false,
cursor_type_changed = false,
redisplay = true,
visible = 1,
iconified = false,
garbaged = false,
wants_modeline = true,
auto_raise = false,
auto_lower = false,
no_split = false,
explicit_name = false,
window_change = false,
window_state_change = false,
mouse_moved = false,
pointer_invisible = false,
frozen_window_starts = false,
output_method = output_initial,
can_set_window_size = true,
after_make_frame = true,
tab_bar_redisplayed = false,
tab_bar_resized = false,
--Type <RET> for more, q to quit, c to continue without paging--
tool_bar_redisplayed = false,
tool_bar_resized = false,
inhibit_horizontal_resize = false,
inhibit_vertical_resize = false,
face_change = true,
inhibit_clear_image_cache = false,
new_size_p = false,
was_invisible = false,
select_mini_window_flag = false,
change_stamp = 14,
number_of_windows = 2,
tab_bar_lines = 0,
tab_bar_height = 0,
n_tab_bar_rows = 0,
n_tab_bar_items = 0,
tool_bar_lines = 0,
tool_bar_height = 0,
n_tool_bar_rows = 0,
n_tool_bar_items = 0,
decode_mode_spec_buffer = 0x613000002f80 '\276' <repeats 200 times>...,
insert_line_cost = 0x0,
delete_line_cost = 0x0,
insert_n_lines_cost = 0x0,
delete_n_lines_cost = 0x0,
text_cols = 80,
text_lines = 24,
text_width = 80,
text_height = 24,
total_cols = 80,
total_lines = 25,
pixel_width = 80,
pixel_height = 25,
new_width = -1,
new_height = -1,
left_pos = 0,
top_pos = 0,
win_gravity = 0,
size_hint_flags = 0,
border_width = 0,
child_frame_border_width = 0,
internal_border_width = 0,
right_divider_width = 0,
bottom_divider_width = 0,
left_fringe_width = 0,
right_fringe_width = 0,
fringe_cols = 0,
menu_bar_lines = 1,
menu_bar_height = 1,
column_width = 1,
line_height = 1,
terminal = 0x621000003d00,
output_data = {
tty = 0x0,
x = 0x0,
w32 = 0x0,
ns = 0x0,
pgtk = 0x0,
haiku = 0x0,
--Type <RET> for more, q to quit, c to continue without paging--
android = 0x0
},
font_driver_list = 0x0,
desired_cursor = FILLED_BOX_CURSOR,
cursor_width = 0,
blink_off_cursor = FILLED_BOX_CURSOR,
blink_off_cursor_width = 0,
config_scroll_bar_width = 0,
config_scroll_bar_cols = 0,
config_scroll_bar_height = 0,
config_scroll_bar_lines = 0,
cost_calculation_baud_rate = 0,
alpha = {0, 0},
alpha_background = 0,
gamma = 0,
extra_line_spacing = 0,
background_pixel = 18446744073709551613,
foreground_pixel = 18446744073709551614
}
(gdb) p SELECTED_FRAME()->output_data
$103 = {
tty = 0x0,
x = 0x0,
w32 = 0x0,
ns = 0x0,
pgtk = 0x0,
haiku = 0x0,
android = 0x0
}
(gdb) p Vframe_list
$104 = XIL(0x7ffff18f6c63)
(gdb) xlist
$105 = 0x6210000175bd
Lisp_Vectorlike
PVEC_FRAME
$106 = (struct frame *) 0x6210000175b8
"F2"
No symbol "PVEC_TS_QUERY" in current context.
(gdb)
If I run (set redisplay_skip_initial_frame nil), then **everything
works as expected**. It redraws well when I resize the terminal. No
black areas visible.
But I want the root issue; I still want to know why it's ¿wrongly?
classified as initial. And then fix that.
So I think this issue (71343) isn't about X focus (we're dealing with
TTYs anyway); it's about how to react to frame size changes. And right
now it's about why it unexpectedly seems a frame as initial frame.
>
> > It's ok if it can't be fixed. I'm surprised that others didn't have
> > this issue; but maybe not many are running TTY emacs (no X) inside an
> > X window.:
>
> It is a rare and not very interesting situation: users aren't expected
> to kill terminals, they are expected to "C-x #" to close Emacs
> displays.
>
By the way, C-x # isn't enough to close any Emacs frame. If I have
opened it by running urxvtcd -e 'emacsclient' '-nw', then later C-x
# doesn't close it, it just says „No server buffers remain to edit“.
But C-x C-c does close it.
The non-repainting issues described above also happen if I close
emacsclient gracefully by C-x C-c. No killing (SIGHUP, SIGKILL, …) is
needed.
Anyway, it seems the problem may be not in the closing, but in the
resizing+redisplaying of the frame that's left. And in the
initial-frame thing, which I'll keep tracing.