emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: "Final" version of tty child frames


From: martin rudalics
Subject: Re: "Final" version of tty child frames
Date: Wed, 8 Jan 2025 10:56:31 +0100
User-agent: Mozilla Thunderbird

>> If you have the time, please also try to look into two issues I raised
>> earlier:
>>
>>   Two further things I noticed: When point in the parent frame is
>>   effectively hidden by the child frame, its cursor sometimes appears at
>>   the right of the child frame and sometimes it's not shown.  I have not
>>   understood the underlying principle for this behavior.  Also when the
>>   selected region in the parent frame is active, its overlay covers the
>>   child frame.  That's ugly.
>
> TTY child frame cursors behave even worse under GPM and a TERM=linux
> terminal.  In this case, the cursor ends up on some lines always
> appearing at the end of lines (ignoring separate frames or windows)
> and sometimes in the right place.  The point position is correct
> though and the cursor does appear correctly once I start pressing
> simple keys like 'A'.

Both issues I raised above seem to be gone with master I pulled today.
Thanks for fixing them.

One thing I noticed is that with code like the following

(defvar tty-child-frame nil)
(defvar tty-child-buffer (get-buffer-create "*tty-child-buffer*"))
(defvar tty-child-window nil)

(defun tty-make-child-frame ()
  (interactive)
  (setq tty-child-frame
        (make-frame
         `((parent-frame . ,(selected-frame))
           (left . 20)
           (top . 10)
           (width . 0.3)
           (height . 0.8)
           (border-width . 0)
           (background-color . "yellow")
           (tool-bar-lines . 0)
           (menu-bar-lines . 0)
           (minibuffer . nil)
           (no-special-glyphs . t)
           )))
  (setq tty-child-window (frame-root-window tty-child-frame))
  (set-window-buffer tty-child-window tty-child-buffer)
  (set-face-background 'internal-border "blue" tty-child-frame)
  (set-face-background 'child-frame-border "blue" tty-child-frame))

(defun tty-toggle-child-frame ()
  (interactive)
  (if (frame-live-p tty-child-frame)
      (if (frame-visible-p tty-child-frame)
          (make-frame-invisible tty-child-frame)
        (make-frame-visible tty-child-frame))
    (tty-make-child-frame)))

(defun tty-switch-to-child-frame ()
  (interactive)
  (if (frame-live-p tty-child-frame)
      (if (frame-visible-p tty-child-frame)
          (if (eq tty-child-frame (selected-frame))
              (select-frame-set-input-focus (frame-parent tty-child-frame))
            (select-frame-set-input-focus tty-child-frame))
        (make-frame-visible tty-child-frame)
        (select-frame-set-input-focus tty-child-frame))
    (tty-make-child-frame)
    (select-frame-set-input-focus tty-child-frame)))

then when I first evaluate 'tty-toggle-child-frame' followed by
'tty-switch-to-child-frame' and I start typing I get an assertion
failure with a backtrace like the below

#0  terminate_due_to_signal (sig=6, backtrace_limit=2147483647) at 
../../src/emacs.c:432
#1  0x0000000000699b76 in die (msg=0x7dfc63 "FRAME_VISIBLE_P (root)", file=0x7df29f 
"../../src/dispnew.c", line=3962) at ../../src/alloc.c:8059
#2  0x0000000000427575 in combine_updates_for_frame (f=0x18662e0, 
inhibit_scrolling=false) at ../../src/dispnew.c:3962
#3  0x00000000004832fc in redisplay_internal () at ../../src/xdisp.c:17699
#4  0x0000000000483719 in redisplay_preserve_echo_area (from_where=8) at 
../../src/xdisp.c:17835
#5  0x000000000060b715 in detect_input_pending_run_timers (do_display=true) at 
../../src/keyboard.c:11579
#6  0x00000000007465d9 in wait_reading_process_output (time_limit=30, nsecs=0, 
read_kbd=-1, do_display=true, wait_for_cell=XIL(0), wait_proc=0x0, 
just_wait_proc=0) at ../../src/process.c:5856
#7  0x0000000000430243 in sit_for (timeout=make_fixnum(30), reading=true, 
display_option=1) at ../../src/dispnew.c:6889
#8  0x00000000005f6383 in read_char (commandflag=1, map=XIL(0x7ff1fcdf4053), 
prev_event=XIL(0), used_mouse_menu=0x7ffc85a5703f, end_time=0x0) at 
../../src/keyboard.c:2925
#9  0x00000000006097f3 in read_key_sequence (keybuf=0x7ffc85a571f0, 
prompt=XIL(0), dont_downcase_last=false, can_return_switch_frame=true, 
fix_current_buffer=true, prevent_redisplay=false, 
disable_text_conversion_p=false) at ../../src/keyboard.c:10746
#10 0x00000000005f1c46 in command_loop_1 () at ../../src/keyboard.c:1424
#11 0x00000000006d06e3 in internal_condition_case (bfun=0x5f1817 <command_loop_1>, 
handlers=XIL(0x90), hfun=0x5f0c99 <cmd_error>) at ../../src/eval.c:1607
#12 0x00000000005f13de in command_loop_2 (handlers=XIL(0x90)) at 
../../src/keyboard.c:1163
#13 0x00000000006cfb39 in internal_catch (tag=XIL(0x122d0), func=0x5f13b4 
<command_loop_2>, arg=XIL(0x90)) at ../../src/eval.c:1286
#14 0x00000000005f1370 in command_loop () at ../../src/keyboard.c:1141
#15 0x00000000005f073b in recursive_edit_1 () at ../../src/keyboard.c:749
#16 0x00000000005f0967 in Frecursive_edit () at ../../src/keyboard.c:832
#17 0x00000000005ec1cd in main (argc=5, argv=0x7ffc85a57828) at 
../../src/emacs.c:2636

Lisp Backtrace:
"redisplay_internal (C function)" (0x0)

The cause is that my 'tty-make-child-frame' has

         `((parent-frame . ,(selected-frame))
...
           (minibuffer . nil)

but the consequences are completely unclear to me.  What happens is that
make_terminal_frame has this

          if (EQ (mini, Qnone) || NILP (mini))
            f = make_frame_without_minibuffer (Qnil, kb, Qnil);

which reenters make_terminal_frame and does

      if (FRAME_LIVE_P (root))
        SET_FRAME_VISIBLE (root, false);

for the old selected "root" frame.

What's the purpose of creating a new top frame without minibuffer here?
We end up with three frames - the initial one, the child frame and the
new root frame without minibuffer.  redisplay_internal eventually
detects here

      Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
      struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));

      if (mini_frame != sf)

that the mini_frame is not the selected frame

        {
          XWINDOW (mini_window)->must_be_updated_p = true;
          update_frame (mini_frame, false);
          if (is_tty_frame (mini_frame))
            combine_updates_for_frame (mini_frame, false);

and the call here crashes because mini_frame is the old root frame but
that frame's visibility has been set to false by the code above.

martin



reply via email to

[Prev in Thread] Current Thread [Next in Thread]