public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Pedro Alves <palves@redhat.com>
To: Patrick Palka <patrick@parcs.ath.cx>, gdb-patches@sourceware.org
Subject: Re: [PATCH] Fix the processing of Meta-key commands in TUI
Date: Wed, 27 Aug 2014 17:06:00 -0000	[thread overview]
Message-ID: <53FE0FF9.9010008@redhat.com> (raw)
In-Reply-To: <1408740286-29326-1-git-send-email-patrick@parcs.ath.cx>

Hey there,

Thanks for looking at this!

On 08/22/2014 09:44 PM, Patrick Palka wrote:
> This patch fixes the annoying bug where key sequences such as Alt_F or
> Alt_B (go forward or backwards by a word) do not behave promptly in TUI.
> You have to press a third key in order for the key sequence to register.
> 
> This is mostly ncurses' fault.  Calling wgetch() normally causes ncurses
> to read only a single key from stdin.  However if the key read is the
> start-sequence key (^[ a.k.a. ESC) then wgetch() reads TWO keys from
> stdin, storing the 2nd key into an internal FIFO buffer and returning
> the start-sequence key.  The extraneous read of the 2nd key makes us
> miss its corresponding stdin event, so the event loop blocks until a
> third key is pressed.  This explains why such key sequences do not
> behave promptly in TUI.
> 
> To fix this issue, we must somehow compensate for the missed stdin event
> corresponding to the 2nd byte of a key sequence.  This patch achieves
> this by hacking  up the stdin event handler to conditionally execute the
> readline callback multiple multiple times in a row.  This is done via a
> new global variable, call_stdin_event_handler_again_p, which is set from
> tui_getc() when we receive a start-sequence key and notice extra pending
> input in the ncurses buffer.

Hmm, I've been staring at this for a while trying to make sense of the
whole thing.  I think there's a larger issue here.

This happens because we enable the "keypad" behavior.  From the ncurses manual:

 The  keypad  option enables the keypad of the user's terminal.  If enabled (bf is TRUE), the user can press a function key (such as an arrow key) and wgetch re‐
 turns a single value representing the function key, as in KEY_LEFT.  If disabled (bf is FALSE), curses does not treat function keys specially  and  the  program
 has to interpret the escape sequences itself.  If the keypad in the terminal can be turned on (made to transmit) and off (made to work locally), turning on this
 option causes the terminal keypad to be turned on when wgetch is called.  The default value for keypad is false.

readline must already be processing escape sequences itself, so
then why we do enable this in the first place?  The answer is that
we want to intercept things like up/down -- when the TUI is active,
those should scroll the source window instead of navigating readline's
history.

This is done in tui_getc:

  if (key_is_command_char (ch))
    {				/* Handle prev/next/up/down here.  */
      ch = tui_dispatch_ctrl_char (ch);
    }

Hacking away keypad, like:

 gdb/tui/tui.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index c30b76c..6174c0f 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -398,7 +398,7 @@ tui_enable (void)
       tui_show_frame_info (0);
       tui_set_layout (SRC_COMMAND, TUI_UNDEFINED_REGS);
       tui_set_win_focus_to (TUI_SRC_WIN);
-      keypad (TUI_CMD_WIN->generic.handle, TRUE);
+      // keypad (TUI_CMD_WIN->generic.handle, TRUE);
       wrefresh (TUI_CMD_WIN->generic.handle);
       tui_finish_init = 0;
     }

indeed makes Alt_F, etc. work.

The main reason I think there's a larger problem here, is that
if curses is reading more than one char from stdin, then that means
that is must be blocking for a bit waiting for the next character,
which is a no-no in an async world, where we want to be processing
target events at the same time.  The man page says:

  While interpreting an input escape sequence, wgetch sets a timer while waiting for the next character.  If notimeout(win, TRUE) is called, then wgetch does not
  set a timer.  The purpose of the timeout is to differentiate between sequences received from a function key and those typed by a user.

Looks like there's a default timeout of 1 second.  Indeed if I set a
breakpoint in wgetch and another right after wgetch is called, and
then I press escape, I see that gdb is stuck inside wgetch for around
one second.  During that time, gdb's own event loop isn't being processed.

Not sure exactly how this is usually handled.  Seems like there
are several knobs that might be able to turn this delay off.
Sounds like we should enable that (whatever the option is),
and handle the timeout ourselves?

Thanks,
Pedro Alves

  reply	other threads:[~2014-08-27 17:06 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-22 20:44 Patrick Palka
2014-08-27 17:06 ` Pedro Alves [this message]
2014-08-27 18:25   ` Patrick Palka
2014-08-28 11:22     ` Pedro Alves
2014-08-28 13:10       ` Patrick Palka
2014-08-28 14:13       ` Patrick Palka
2014-08-28 15:59         ` Pedro Alves
2014-08-28 16:22           ` Patrick Palka
2014-08-28 17:41         ` Patrick Palka
2014-08-28 17:44           ` Patrick Palka
2014-08-28 11:31 ` Pedro Alves
2014-08-28 14:18   ` Patrick Palka
2014-08-28 16:13     ` Pedro Alves
2014-08-28 16:26       ` Patrick Palka
2014-11-14 19:12       ` Patrick Palka
2014-11-23 10:08         ` Joel Brobecker
2014-11-23 12:41           ` Patrick Palka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=53FE0FF9.9010008@redhat.com \
    --to=palves@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=patrick@parcs.ath.cx \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).