Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Alves <pedro@palves.net>
To: Hannes Domani <ssbssa@yahoo.de>,
	Hannes Domani via Gdb-patches <gdb-patches@sourceware.org>,
	Tom Tromey <tom@tromey.com>
Cc: Joel Brobecker <brobecker@adacore.com>
Subject: POC: Make the TUI command window support the mouse (Re: [PATCHv3 1/2] Initial TUI mouse support)
Date: Sat, 12 Jun 2021 03:41:08 +0100	[thread overview]
Message-ID: <bb8428c5-06fb-c86f-2786-bb6c46ae0886@palves.net> (raw)
In-Reply-To: <287323544.8784317.1623409369460@mail.yahoo.com>

On 2021-06-11 12:02 p.m., Hannes Domani wrote:
>  Am Donnerstag, 10. Juni 2021, 20:47:01 MESZ hat Tom Tromey <tom@tromey.com> Folgendes geschrieben:
> 
>>>>>>> "Hannes" == Hannes Domani via Gdb-patches <gdb-patches@sourceware.org> writes:
>>
>> Hannes> I imagine the same is true for mouse escape sequences.
>> Hannes> So I would just disable the mouse when the command window has focus, but
>> Hannes> what do you think?
>>
>> I think this is a good fallback to have, but it would be better if we
>> could make it really work somehow.  The problem with doing this is that
>> if the command window has focus, then things like clicking in the source
>> to set a breakpoint will not work.
> 
> That would probably mean that keypad also has to be enabled when the
> command window has focus.
> I did a short test where I tried this, but then gdb crashed somewhere in
> readline, and I stopped there, because I didn't want to debug readline code.

We disable the keypad in the command window because we want to pass all escape
sequences to readline, unprocessed by ncurses, so that e.g., up/down navigates
the command history, left/right moves the cursor position, etc., just like if
you weren't in the TUI.

I first thought of fixing this by enabling the keypad, and then where we handle
KEY_UP, etc., special case the command window, and call readline functions that do
what you'd expect.  But the thing is that ends up being a poor readline emulation,
and I didn't like where this was going.  Especially when I realized that for example,
when you're in the middle for a reverse-search (c-r), KEY_UP does something different.
Etc.

I had a different idea to make this all work.  Warning, this is either a brilliant hack,
or a really nasty hack, depending on perspective.  :-)

The idea is to keep the keypad disabled in the command window.  However,
we need to enable the keypad for ncurses to process mouse escape sequences.
This is a conflict.  So here's the main trick behind the idea.  It breaks the conflict.
Create a separate ncurses screen/terminal, with newterm, which reads from a pipe instead
of from stdin.  Then, flush data from stdin into this pipe, BUT, make sure to never flush
a non-mouse escape sequence into the pipe.  It's like the pipe is stdin, but with any
non-mouse escape sequence filtered out.  This way, ncurses only either sees mouse
escape sequences or normal ASCII keys.  In order to do this, we need to use
a separate thread to flush stdin to the pipe.

I gave this a try the other weekend, and ran into issues.  Today/tonight I gave it
another go, and got it working.  It is a bit rough around the edges, but
seems to work nicely.

From a3bf7056c7dee837816807d41d33abda45cfd51d Mon Sep 17 00:00:00 2001
From: Pedro Alves <pedro@palves.net>
Date: Sat, 5 Jun 2021 19:11:09 +0100
Subject: [PATCH] Make the TUI command window support the mouse

Change-Id: Ie0a7d849943cfb47f4a6589e1c73341563740fa9
---
 gdb/tui/tui-io.c | 549 ++++++++++++++++++++++++++++++++++++++++++++---
 gdb/tui/tui-io.h |   3 +
 gdb/tui/tui.c    |   4 +
 3 files changed, 527 insertions(+), 29 deletions(-)

diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c
index 7df0e2f1bd3..6c1c3f2f5f0 100644
--- a/gdb/tui/tui-io.c
+++ b/gdb/tui/tui-io.c
@@ -946,6 +946,34 @@ tui_initialize_io (void)
 #endif
 }
 
+/* Dispatch the correct tui function based upon the mouse event.  */
+
+static void
+tui_dispatch_mouse_event (const MEVENT &mev)
+{
+  for (tui_win_info *wi : all_tui_windows ())
+    if (mev.x > wi->x && mev.x < wi->x + wi->width - 1
+	&& mev.y > wi->y && mev.y < wi->y + wi->height - 1)
+      {
+	if ((mev.bstate & BUTTON1_CLICKED) != 0
+	    || (mev.bstate & BUTTON2_CLICKED) != 0
+	    || (mev.bstate & BUTTON3_CLICKED) != 0)
+	  {
+	    int button = (mev.bstate & BUTTON1_CLICKED) != 0 ? 1
+	      :         ((mev.bstate & BUTTON2_CLICKED) != 0 ? 2
+			 : 3);
+	    wi->click (mev.x - wi->x - 1, mev.y - wi->y - 1, button);
+	  }
+#ifdef BUTTON5_PRESSED
+	else if ((mev.bstate & BUTTON4_PRESSED) != 0)
+	  wi->backward_scroll (3);
+	else if ((mev.bstate & BUTTON5_PRESSED) != 0)
+	  wi->forward_scroll (3);
+#endif
+	break;
+      }
+}
+
 /* Dispatch the correct tui function based upon the control
    character.  */
 static unsigned int
@@ -959,7 +987,9 @@ tui_dispatch_ctrl_char (unsigned int ch)
 
   /* If no window has the focus, or if the focus window can't scroll,
      just pass the character through.  */
-  if (win_info == NULL || !win_info->can_scroll ())
+  if (win_info == NULL
+      || (win_info != TUI_CMD_WIN
+	  && !win_info->can_scroll ()))
     return ch;
 
   switch (ch)
@@ -988,30 +1018,8 @@ tui_dispatch_ctrl_char (unsigned int ch)
     case KEY_MOUSE:
 	{
 	  MEVENT mev;
-	  if (getmouse (&mev) != OK)
-	    break;
-
-	  for (tui_win_info *wi : all_tui_windows ())
-	    if (mev.x > wi->x && mev.x < wi->x + wi->width - 1
-		&& mev.y > wi->y && mev.y < wi->y + wi->height - 1)
-	      {
-		if ((mev.bstate & BUTTON1_CLICKED) != 0
-		    || (mev.bstate & BUTTON2_CLICKED) != 0
-		    || (mev.bstate & BUTTON3_CLICKED) != 0)
-		  {
-		    int button = (mev.bstate & BUTTON1_CLICKED) != 0 ? 1
-		      :         ((mev.bstate & BUTTON2_CLICKED) != 0 ? 2
-				 : 3);
-		    wi->click (mev.x - wi->x - 1, mev.y - wi->y - 1, button);
-		  }
-#ifdef BUTTON5_PRESSED
-		else if ((mev.bstate & BUTTON4_PRESSED) != 0)
-		  wi->backward_scroll (3);
-		else if ((mev.bstate & BUTTON5_PRESSED) != 0)
-		  wi->forward_scroll (3);
-#endif
-		break;
-	      }
+	  if (getmouse (&mev) == OK)
+	    tui_dispatch_mouse_event (mev);
 	}
       break;
 #endif
@@ -1067,6 +1075,251 @@ tui_inject_newline_into_command_window ()
     }
 }
 
+/* True if the mouse thread is the one reading stdin.  */
+static volatile bool mouse_thread_stdin = false;
+static volatile bool mouse_thread_stdin_out = false;
+
+/* The handle to the mouse thread.  */
+static pthread_t mouse_thread;
+
+/* Pipe used to wake up / interrupt the mouse thread.  */
+static int intr_mouse_thread[2];
+
+/* Pipe used to feed input data into the magic mouse screen.  */
+static int mouse_input_pipe[2];
+
+/* Data we've read from stdin but did not want passed to ncurses.  */
+static std::vector<int> mouse_chars;
+
+/* True if the next tut_getc_1 should drain from CHARS.  */
+static bool drain_mouse_chars;
+
+/* Enable debugging the mouse screen and thread processing.  */
+static bool debug_mouse_thread = 0;
+
+/* The escape sequence header for a mouse event.  */
+static const unsigned char mouse_seq[] = { 27, '[', 'M' };
+/* Pointer to the next expected character in a mouse escape sequence.
+   If we haven't seen any character of the sequence yet, this points
+   to the first character of MOUSE_SEQ.  If we've seen the whole
+   sequence header, this points to one-past-last of MOUSE_SEQ.  */
+static const unsigned char *mouse_seq_pos = nullptr;
+
+/* True if the last key we got out of gdb_wgetch was a KEY_MOUSE.  In
+   that case, continue reading chars using the magic mouse screen.  */
+static bool last_key_was_mouse = false;
+
+/* The mouse screen used to read mouse keys.  This screen's main
+   window has the keypad enabled so that it processes mouse escape
+   sequences.  But instead of reading from stdin, it reads from a
+   pipe.  This pipe is filled with data read from stdin, but filtered
+   -- it won't ever include non-mouse escape sequences.  This means
+   that reading from this curses screen either returns KEY_MOUSE, or
+   regular ASCII key, never KEY_UP, etc.  */
+static SCREEN *mouse_screen;
+
+/* Write CH to the mouse input pipe.  */
+
+static void
+write_mouse_pipe (int ch)
+{
+  unsigned char buf = ch;
+  write (mouse_input_pipe[1], &buf, 1);
+}
+
+/* Wake up the mouse thread.  */
+
+static void
+wake_mouse_thread ()
+{
+  unsigned char buf = '+';
+  write (intr_mouse_thread[1], &buf, 1);
+}
+
+/* Flush the INTR_MOUSE_THREAD pipe.  */
+
+static void
+flush_intr_mouse_pipe ()
+{
+  int ret;
+
+  do
+    {
+      char buf;
+      ret = read (intr_mouse_thread[0], &buf, 1);
+    }
+  while (ret >= 0 || (ret == -1 && errno == EINTR));
+}
+
+/* Flush data out of stdin, into the MOUSE_INPUT_PIPE.  Except, if we
+   see an escape sequence that isn't a mouse escape sequence, don't
+   put it in the pipe.  The idea is that we never want ncurses to see
+   non-mouse escape sequences.  We want to pass those directly to
+   readline.  E.g., we don't want ncurses to return KEY_UP, we want
+   readline instead to see the "key up" escape sequence, and call
+   "previous-history".  */
+
+static void *
+mouse_thread_fn (void *)
+{
+  /* XXXX: Block signals in parent before spawning this.  */
+
+  while (1)
+    {
+      fd_set readfds;
+
+      FD_ZERO (&readfds);
+      FD_SET (intr_mouse_thread[0], &readfds);
+
+      if (mouse_thread_stdin)
+	FD_SET (0, &readfds);
+
+      if (select (intr_mouse_thread[0] + 1, &readfds, NULL, NULL, NULL) == -1)
+	{
+	  if (errno == EINTR)
+	    continue;
+
+	  /* XXX: shouldn't throw...  */
+	  perror_with_name (("select"));
+	}
+
+      if (FD_ISSET (0, &readfds))
+	{
+	  unsigned char ch;
+	  int n = read (0, &ch, 1);
+	  if (n == 1)
+	    {
+	      if (ch == *mouse_seq_pos)
+		{
+		  /* Looks like another character part of a mouse
+		     escape sequence.  */
+		  mouse_seq_pos++;
+
+		  if (mouse_seq_pos == mouse_seq + sizeof (mouse_seq))
+		    {
+		      /* Yup, we saw "ESC [ M".  */
+
+		      if (debug_mouse_thread)
+			fprintf (stderr, "thread: got mouse sequence header\n");
+
+		      for (size_t i = 0; i < sizeof (mouse_seq); i++)
+			{
+			  write_mouse_pipe (mouse_seq[i]);
+			  if (debug_mouse_thread)
+			    fprintf (stderr, "thread: %c (%d) ",
+				     mouse_seq[i], mouse_seq[i]);
+			}
+
+		      mouse_seq_pos = mouse_seq;
+		    }
+		}
+	      else if (mouse_seq_pos > mouse_seq)
+		{
+		  if (debug_mouse_thread)
+		    fprintf (stderr,
+			     "thread: non-mouse escape sequence, STOP!\n");
+
+		  /* Store the sequence in MOUSE_CHARS instead of in
+		     the pipe.  We don't want ncurses to see it.  */
+		  for (size_t i = 0; i < mouse_seq_pos - mouse_seq; i++)
+		    {
+		      mouse_chars.push_back (mouse_seq[i]);
+		      if (debug_mouse_thread)
+			fprintf (stderr, "thread: %c (%d) ",
+				 mouse_seq[i], mouse_seq[i]);
+		    }
+		  mouse_chars.push_back (ch);
+		  if (debug_mouse_thread)
+		    fprintf (stderr, "thread: %c (%d) ", ch, ch);
+
+		  /* The mainline code is blocked in wgetch, and we
+		     need to wake it up, but we don't want to let
+		     ncurses see this sequence.  Solve this by putting
+		     a 0/NIL character in the pipe.  That pass through
+		     wgetch and we will end up returning 0 to
+		     readline, which readline interprets as "no op",
+		     exactly what we want.  Phew!  */
+		  write_mouse_pipe (0);
+
+		  /* Reset the sequence position pointer, and stop
+		     reading stdin until the mainline code tells us
+		     otherwise.  */
+		  mouse_seq_pos = mouse_seq;
+		  mouse_thread_stdin = false;
+		}
+	      else
+		{
+		  write_mouse_pipe (ch);
+
+		  if (debug_mouse_thread)
+		    fprintf (stderr, "thread: %c (%d) ", ch, ch);
+		}
+	    }
+	  else
+	    {
+	      if (debug_mouse_thread)
+		fprintf (stderr, "thread: => -1!");
+	    }
+	  if (debug_mouse_thread)
+	    fflush (stderr);
+	}
+
+      if (FD_ISSET (intr_mouse_thread[0], &readfds))
+	{
+	  int ret;
+
+	  if (debug_mouse_thread)
+	    fprintf (stderr, "break thread\n");
+
+	  do
+	    {
+	      char buf;
+	      ret = read (intr_mouse_thread[0], &buf, 1);
+	    }
+	  while (ret == -1 && errno == EINTR);
+
+	  mouse_thread_stdin_out = mouse_thread_stdin;
+	  continue;
+	}
+    }
+
+  return nullptr;
+}
+
+/* Initialize the special mouse screen, and all auxiliary bits.  */
+
+void
+init_mouse_screen ()
+{
+  /* Pseudo-stdin pipe for the ncurses mouse "terminal".  */
+  if (gdb_pipe_cloexec (mouse_input_pipe) != 0)
+    error (_("Cannot create pipe for mouse"));
+
+  /* The self-trick pipe used to wake up / interrupt the mouse
+     thread.  */
+  if (gdb_pipe_cloexec (intr_mouse_thread) != 0)
+    error (_("Cannot create pipe for mouse interruption"));
+  fcntl (intr_mouse_thread[0], F_SETFL, O_NONBLOCK);
+  fcntl (intr_mouse_thread[1], F_SETFL, O_NONBLOCK);
+
+  /* Create the mouse terminal.  It reads from the mouse input pipe,
+     and writes nowhere.  */
+  FILE *in = fdopen (mouse_input_pipe[0], "r");
+  FILE *out = fopen ("/dev/null", "w+");
+  setvbuf (in, NULL, _IONBF, BUFSIZ);
+
+  mouse_screen = newterm (NULL, out, in);
+  mousemask (ALL_MOUSE_EVENTS, NULL);
+
+  /* Enable the keypad, we want to use this terminal to process mouse
+     escape codes.  */
+  WINDOW *w = stdscr;
+  keypad (w, TRUE);
+
+  /* Spawn the mouse thread.  */
+  pthread_create (&mouse_thread, nullptr, mouse_thread_fn, nullptr);
+}
+
 /* Main worker for tui_getc.  Get a character from the command window.
    This is called from the readline package, but wrapped in a
    try/catch by tui_getc.  */
@@ -1084,14 +1337,251 @@ tui_getc_1 (FILE *fp)
   tui_readline_output (0, 0);
 #endif
 
-  ch = gdb_wgetch (w);
+  if (tui_win_with_focus () == TUI_CMD_WIN && current_ui->command_editing)
+    {
+      if (drain_mouse_chars)
+	{
+	  ch = mouse_chars.front ();
+	  mouse_chars.erase (mouse_chars.begin ());
+	  if (debug_mouse_thread)
+	    fprintf (stderr, "drain: got %c (%d), ", ch, ch);
+	  if (mouse_chars.empty ())
+	    {
+	      drain_mouse_chars = false;
+	      if (debug_mouse_thread)
+		fprintf (stderr, " : done\r\n");
+	    }
+	  else
+	    call_stdin_event_handler_again_p = 1;
+	  return ch;
+	}
+      else if (!last_key_was_mouse)
+	{
+	  ch = gdb_wgetch (w);
+	}
+
+      if (last_key_was_mouse || key_is_start_sequence (ch))
+	{
+	  /* Process this key sequence with the special mouse ncurses
+	     screen, which has the keypad enabled, and reads from
+	     MOUSE_INPUT_PIPE.  */
+
+	  /* Set the current screen to the mouse screen.  */
+	  WINDOW *prev_stdscr = stdscr;
+	  SCREEN *prev_s = set_term (mouse_screen);
+	  /* The mouse WINDOW.  */
+	  WINDOW *mw = stdscr;
+
+	  if (last_key_was_mouse)
+	    {
+	      if (debug_mouse_thread)
+		fprintf (stderr, "last key was mouse\r\n");
+	    }
+
+	  /* If we're just starting a sequence, block waiting for the
+	     whole sequence.  If we're here because we returned a
+	     mouse event before and we're now draining the curses
+	     buffer, disable blocking.  */
+	  if (last_key_was_mouse)
+	    nodelay (mw, TRUE);
+	  else
+	    nodelay (mw, FALSE);
+
+	  flush_intr_mouse_pipe ();
+
+	  /* If we're starting a new sequence, reset the sequence
+	     position.  If we last saw a mouse key, then the mouse
+	     thread may have read a partial mouse event out of stdin,
+	     so we need to let it continue the sequence where it left
+	     it last.  */
+	  if (!last_key_was_mouse)
+	    mouse_seq_pos = &mouse_seq[1];
+
+	  /* Set the thread reading from stdin.  */
+	  mouse_thread_stdin = true;
+	  wake_mouse_thread ();
+	  while (!mouse_thread_stdin_out)
+	    ;
+
+	  using namespace std::chrono;
+
+	  steady_clock::time_point before = steady_clock::now ();
+
+	  /* Read one cooked key out of the mouse window.  */
+	  ch = gdb_wgetch (mw);
+
+	  steady_clock::time_point after = steady_clock::now ();
+
+	  auto diff = after - before;
+	  seconds s = duration_cast<seconds> (diff);
+	  microseconds us = duration_cast<microseconds> (diff - s);
+	  if (debug_mouse_thread)
+	    fprintf (stderr, "wgetch took: %ld.%06ld\n",
+		     (long) s.count (),
+		     (long) us.count ());
+
+	  /* Tell the thread to stop reading stdin, and wait until it
+	     acknowledges it.  */
+	  mouse_thread_stdin = false;
+	  wake_mouse_thread ();
+	  while (mouse_thread_stdin_out)
+	    ;
+
+	  if (ch == ERR)
+	    {
+	      /* We get here if the previous key returned was a mouse
+		 key, and thus disabled blocked in order to flush all
+		 keys.  ERR means there are no more keys in the curses
+		 buffer.  */
+	      if (debug_mouse_thread)
+		fprintf (stderr, "got ERR\r\n");
+
+	      /* Stop draining curses.  */
+	      last_key_was_mouse = false;
+
+	      /* If the thread saw a non-mouse escape sequence, we
+		 need to drain it next.  */
+	      if (!mouse_chars.empty ())
+		{
+		  drain_mouse_chars = true;
+		  call_stdin_event_handler_again_p = 1;
+		}
+
+	      ch = 0;
+	    }
+	  else if (ch == KEY_MOUSE)
+	    {
+	      if (debug_mouse_thread)
+		fprintf (stderr, "KEY_MOUSE\n");
+
+	      /* Process this mouse key, and set up to drain other
+		 keys that ncurses may have read into its internal
+		 buffer already.  */
+	      last_key_was_mouse = true;
+	      call_stdin_event_handler_again_p = 1;
+
+	      /* Get the mouse event.  This must be called with the
+		 mouse screen as current.  */
+	      MEVENT mev;
+	      if (getmouse (&mev) == OK)
+		{
+		  /* Now handle the mouse event.  This must be done
+		     with the normal screen as current.  */
+		  set_term (prev_s);
+		  stdscr = prev_stdscr;
+
+		  /* Handle prev/next/up/down here.  */
+		  tui_dispatch_mouse_event (mev);
+		}
+
+	      return 0;
+	    }
+	  else
+	    {
+	      if (debug_mouse_thread)
+		fprintf (stderr, "not KEY_MOUSE, %c (%d)\n", ch, ch);
+
+	      last_key_was_mouse = false;
+
+	      /* Drain data buffered on the ncurses side and/or in the
+		 pipe.  */
+	      nodelay (mw, TRUE);
+
+	      /* Data already in MOUSE_CHARS must be returned to
+		 readline _after_ the data ncurses already fetched
+		 from the pipe into its own internal buffer.  IOW, the
+		 ncurses buffered data must be prepended into
+		 MOUSE_CHARS.  Start by draining ncurses data into a
+		 temporary vector.  */
+	      std::vector<int> tmp_chars;
+	      int ch2 = gdb_wgetch (mw);
+	      if (ch2 != ERR)
+		{
+		  if (debug_mouse_thread)
+		    fprintf (stderr, "more data!: %c (%d)", ch2, ch2);
+		  gdb_assert (ch2 != KEY_MOUSE);
+		  tmp_chars.push_back (ch2);
+		  while (1)
+		    {
+		      ch2 = gdb_wgetch (mw);
+		      if (ch2 == ERR)
+			{
+			  if (debug_mouse_thread)
+			    fprintf (stderr, ", ERR");
+			  break;
+			}
+		      else
+			{
+			  if (debug_mouse_thread)
+			    fprintf (stderr, ", %c (%d)", ch2, ch2);
+			  gdb_assert (ch2 != KEY_MOUSE);
+			  tmp_chars.push_back (ch2);
+			}
+		    }
+		  if (debug_mouse_thread)
+		    {
+		      fprintf (stderr, "\n");
+		      fflush (stderr);
+		    }
+		}
+
+	      nodelay (mw, FALSE);
+
+	      /* Now append the data that was already in MOUSE_CHARS
+		 in the temporary vector.  */
+	      tmp_chars.insert (tmp_chars.end (),
+				mouse_chars.begin (), mouse_chars.end ());
+
+	      /* And make the result the new MOUSE_CHARS.  */
+	      mouse_chars = std::move (tmp_chars);
+
+	      if (debug_mouse_thread)
+		fprintf (stderr, "got %c (%d), ", ch, ch);
+	      if (!mouse_chars.empty ())
+		{
+		  drain_mouse_chars = true;
+		  call_stdin_event_handler_again_p = 1;
+		}
+	    }
+
+	  /* Restore the regular screen as current.  */
+	  set_term (prev_s);
+	  stdscr = prev_stdscr;
+	}
+      else
+	{
+	  if (debug_mouse_thread)
+	    fprintf (stderr, "tui_get_c_1: not escape: %c (%d)\n", ch, ch);
+	}
+    }
+  else
+    {
+      using namespace std::chrono;
+
+      steady_clock::time_point before = steady_clock::now ();
+
+      ch = gdb_wgetch (w);
+
+      steady_clock::time_point after = steady_clock::now ();
+
+      auto diff = after - before;
+      seconds s = duration_cast<seconds> (diff);
+      microseconds us = duration_cast<microseconds> (diff - s);
+#if 0
+      fprintf (stderr, "wgetch took: %ld.%06ld\n",
+	       (long) s.count (),
+	       (long) us.count ());
+#endif
+
+      /* Handle prev/next/up/down here.  */
+      ch = tui_dispatch_ctrl_char (ch);
+    }
 
-  /* Handle prev/next/up/down here.  */
-  ch = tui_dispatch_ctrl_char (ch);
-  
   if (ch == KEY_BACKSPACE)
     return '\b';
 
+#if 0
+  /* XXX: see about re-enabling this.  */
   if (current_ui->command_editing && key_is_start_sequence (ch))
     {
       int ch_pending;
@@ -1117,6 +1607,7 @@ tui_getc_1 (FILE *fp)
 	  call_stdin_event_handler_again_p = 1;
 	}
     }
+#endif
 
   return ch;
 }
diff --git a/gdb/tui/tui-io.h b/gdb/tui/tui-io.h
index 760532140f1..e4e9bc745b9 100644
--- a/gdb/tui/tui-io.h
+++ b/gdb/tui/tui-io.h
@@ -60,4 +60,7 @@ extern cli_ui_out *tui_old_uiout;
    next line.  */
 extern void tui_inject_newline_into_command_window ();
 
+/* Initialize the mouse screen.  */
+extern void init_mouse_screen ();
+
 #endif /* TUI_TUI_IO_H */
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index 529fc62c9ac..490cdb69dda 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -383,6 +383,10 @@ tui_enable (void)
       if (!gdb_stderr->isatty ())
 	error (_("Cannot enable the TUI when output is not a terminal"));
 
+      /* This must be done before the newterm below, otherwise we end
+	 up with a messed up (main) terminal.  */
+      init_mouse_screen ();
+
       s = newterm (NULL, stdout, stdin);
 #ifdef __MINGW32__
       /* The MinGW port of ncurses requires $TERM to be unset in order

base-commit: a53755664f5f904aefd0d0b87e12f9adb6b69129
-- 
2.26.2


  reply	other threads:[~2021-06-12  2:41 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20210603151453.15248-1-ssbssa.ref@yahoo.de>
2021-06-03 15:14 ` [PATCHv3 1/2] Initial TUI mouse support Hannes Domani via Gdb-patches
2021-06-03 15:14   ` [PATCHv3 2/2] Forward mouse click to python TUI window Hannes Domani via Gdb-patches
2021-06-03 17:16     ` Eli Zaretskii via Gdb-patches
2021-06-04 13:52     ` Tom Tromey
2021-06-04 13:51   ` [PATCHv3 1/2] Initial TUI mouse support Tom Tromey
2021-06-04 14:21     ` Hannes Domani via Gdb-patches
2021-06-04 15:20       ` Pedro Alves
2021-06-04 16:06         ` Hannes Domani via Gdb-patches
2021-06-04 16:23           ` Pedro Alves
2021-06-04 18:59             ` Eli Zaretskii via Gdb-patches
2021-06-04 18:57           ` Eli Zaretskii via Gdb-patches
2021-06-04 16:29         ` Pedro Alves
2021-06-04 16:48           ` Hannes Domani via Gdb-patches
2021-06-04 18:05             ` Joel Brobecker
2021-06-04 18:13           ` Simon Marchi via Gdb-patches
2021-06-04 18:39             ` Joel Brobecker
2021-06-04 20:31             ` Pedro Alves
2021-06-04 20:43               ` Pedro Alves
2021-06-04 21:15               ` Hannes Domani via Gdb-patches
2021-06-04 22:19                 ` Pedro Alves
2021-06-10 18:44               ` Tom Tromey
2021-06-13 17:26                 ` Pedro Alves
2021-06-18 15:01                   ` Tom Tromey
2021-06-18 17:42                     ` Pedro Alves
2021-06-04 18:46           ` Tom Tromey
2021-06-04 20:54             ` Pedro Alves
2021-06-04 23:48               ` Pedro Alves
2021-06-05 14:40                 ` Hannes Domani via Gdb-patches
2021-06-06  5:46                   ` Eli Zaretskii via Gdb-patches
2021-06-10 18:46                   ` Tom Tromey
2021-06-11 11:02                     ` Hannes Domani via Gdb-patches
2021-06-12  2:41                       ` Pedro Alves [this message]
2021-06-12 12:32                         ` POC: Make the TUI command window support the mouse (Re: [PATCHv3 1/2] Initial TUI mouse support) Hannes Domani via Gdb-patches
2021-06-12 18:08                           ` Pedro Alves
2021-06-13  2:46                             ` [PATCH v2] Make the TUI command window support the mouse Pedro Alves
2021-06-13 10:35                               ` Eli Zaretskii via Gdb-patches
2021-06-13 17:29                                 ` Pedro Alves
2021-06-13 18:02                                   ` Eli Zaretskii via Gdb-patches
2021-06-13 18:13                                     ` Pedro Alves
2021-06-13 13:04                               ` Hannes Domani via Gdb-patches
2021-06-13 17:25                                 ` [PATCH v3] " Pedro Alves
2021-06-13 17:55                                   ` Hannes Domani via Gdb-patches
2021-06-13 17:59                                     ` Pedro Alves
2021-06-17 11:04                                       ` [PUSHED v4] " Pedro Alves

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=bb8428c5-06fb-c86f-2786-bb6c46ae0886@palves.net \
    --to=pedro@palves.net \
    --cc=brobecker@adacore.com \
    --cc=gdb-patches@sourceware.org \
    --cc=ssbssa@yahoo.de \
    --cc=tom@tromey.com \
    /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