[PATCH 2/4] Rename tui_suppress_output

Tom Tromey tom@tromey.com
Wed Jul 10 23:23:04 GMT 2024


This patch renames tui_suppress_output to the more descriptive
tui_batch_rendering.  This code was never really correct, and was
based on a misunderstanding of the curses API.  The updated comments
describe the intended use of this class.

This also removes the erroneous tui_win_info::no_refresh.
wnoutrefresh does not prevent any output; rather, it copies from one
curses buffer to another but (unlike woutrefresh) without then
flushing to the screen.

tui_batch_rendering now works in the correct way: calling doupdate in
the destructor of the outermost instance, thus batching all screen
output until that point.

The patch adds instantiations of tui_batch_rendering to various spots,
to make sure it is active when refreshing.
---
 gdb/python/py-tui.c      | 10 ++++++++++
 gdb/tui/tui-data.h       |  7 -------
 gdb/tui/tui-layout.c     |  2 ++
 gdb/tui/tui-regs.c       |  4 ++--
 gdb/tui/tui-win.c        |  6 +-----
 gdb/tui/tui-wingeneral.c | 19 ++++++-------------
 gdb/tui/tui-wingeneral.h | 16 +++++++++-------
 gdb/tui/tui-winsource.c  |  2 +-
 gdb/tui/tui.c            |  2 +-
 9 files changed, 32 insertions(+), 36 deletions(-)

diff --git a/gdb/python/py-tui.c b/gdb/python/py-tui.c
index 984fa9b6b45..038feac3781 100644
--- a/gdb/python/py-tui.c
+++ b/gdb/python/py-tui.c
@@ -180,6 +180,8 @@ tui_py_window::~tui_py_window ()
 void
 tui_py_window::rerender ()
 {
+  tui_batch_rendering batch;
+
   tui_win_info::rerender ();
 
   gdbpy_enter enter_py;
@@ -206,6 +208,8 @@ tui_py_window::rerender ()
 void
 tui_py_window::do_scroll_horizontal (int num_to_scroll)
 {
+  tui_batch_rendering batch;
+
   gdbpy_enter enter_py;
 
   if (PyObject_HasAttrString (m_window.get (), "hscroll"))
@@ -220,6 +224,8 @@ tui_py_window::do_scroll_horizontal (int num_to_scroll)
 void
 tui_py_window::do_scroll_vertical (int num_to_scroll)
 {
+  tui_batch_rendering batch;
+
   gdbpy_enter enter_py;
 
   if (PyObject_HasAttrString (m_window.get (), "vscroll"))
@@ -242,6 +248,8 @@ tui_py_window::resize (int height_, int width_, int origin_x_, int origin_y_)
 void
 tui_py_window::click (int mouse_x, int mouse_y, int mouse_button)
 {
+  tui_batch_rendering batch;
+
   gdbpy_enter enter_py;
 
   if (PyObject_HasAttrString (m_window.get (), "click"))
@@ -258,6 +266,8 @@ tui_py_window::output (const char *text, bool full_window)
 {
   if (m_inner_window != nullptr)
     {
+      tui_batch_rendering batch;
+
       if (full_window)
 	werase (m_inner_window.get ());
 
diff --git a/gdb/tui/tui-data.h b/gdb/tui/tui-data.h
index b9922db574d..14c9b87c8c0 100644
--- a/gdb/tui/tui-data.h
+++ b/gdb/tui/tui-data.h
@@ -117,13 +117,6 @@ struct tui_win_info
     return true;
   }
 
-  /* Disable output until the next call to doupdate.  */
-  void no_refresh ()
-  {
-    if (handle != nullptr)
-      wnoutrefresh (handle.get ());
-  }
-
   /* Called after the tab width has been changed.  */
   virtual void update_tab_width ()
   {
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 665b5211559..2b6cb3194ae 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -61,6 +61,8 @@ std::vector<tui_win_info *> tui_windows;
 void
 tui_apply_current_layout (bool preserve_cmd_win_size_p)
 {
+  tui_batch_rendering defer;
+
   for (tui_win_info *win_info : tui_windows)
     win_info->make_visible (false);
 
diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c
index 677facee362..38ddd2336fe 100644
--- a/gdb/tui/tui-regs.c
+++ b/gdb/tui/tui-regs.c
@@ -492,11 +492,11 @@ tui_reg_command (const char *args, int from_tty)
     {
       size_t len = strlen (args);
 
+      tui_batch_rendering suppress;
+
       /* Make sure the curses mode is enabled.  */
       tui_enable ();
 
-      tui_suppress_output suppress;
-
       /* Make sure the register window is visible.  If not, select an
 	 appropriate layout.  We need to do this before trying to run the
 	 'next' or 'prev' commands.  */
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index c67c4f500df..e9a8e4651ea 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -473,11 +473,7 @@ void
 tui_refresh_all_win (void)
 {
   clearok (curscr, TRUE);
-  for (tui_win_info *win_info : all_tui_windows ())
-    {
-      if (win_info->is_visible ())
-	win_info->refresh_window ();
-    }
+  doupdate ();
 }
 
 void
diff --git a/gdb/tui/tui-wingeneral.c b/gdb/tui/tui-wingeneral.c
index d113d77c4ab..963a1658ae5 100644
--- a/gdb/tui/tui-wingeneral.c
+++ b/gdb/tui/tui-wingeneral.c
@@ -27,33 +27,27 @@
 
 #include "gdb_curses.h"
 
-/* This is true if we're currently suppressing output, via
-   wnoutrefresh.  This is needed in case we create a new window while
-   in this mode.  */
+/* This is true when there is a live instance of tui_batch_rendering.
+   The outermost tui_batch_rendering will cause a flush to the
+   screen.  */
 
 static bool suppress_output;
 
 /* See tui-data.h.  */
 
-tui_suppress_output::tui_suppress_output ()
+tui_batch_rendering::tui_batch_rendering ()
   : m_saved_suppress (suppress_output)
 {
   suppress_output = true;
-
-  for (const auto &win : all_tui_windows ())
-    win->no_refresh ();
 }
 
 /* See tui-data.h.  */
 
-tui_suppress_output::~tui_suppress_output ()
+tui_batch_rendering::~tui_batch_rendering ()
 {
   suppress_output = m_saved_suppress;
   if (!suppress_output)
     doupdate ();
-
-  for (const auto &win : all_tui_windows ())
-    win->refresh_window ();
 }
 
 /* See tui-data.h.  */
@@ -61,8 +55,7 @@ tui_suppress_output::~tui_suppress_output ()
 void
 tui_wrefresh (WINDOW *win)
 {
-  if (!suppress_output)
-    wrefresh (win);
+  wnoutrefresh (win);
 }
 
 /* See tui-data.h.  */
diff --git a/gdb/tui/tui-wingeneral.h b/gdb/tui/tui-wingeneral.h
index 652cef95733..6387afdcbaa 100644
--- a/gdb/tui/tui-wingeneral.h
+++ b/gdb/tui/tui-wingeneral.h
@@ -29,18 +29,20 @@ struct tui_win_info;
 extern void tui_unhighlight_win (struct tui_win_info *);
 extern void tui_highlight_win (struct tui_win_info *);
 
-/* An RAII class that suppresses output on construction (calling
-   wnoutrefresh on the existing windows), and then flushes the output
-   (via doupdate) when destroyed.  */
+/* An RAII class that calls doupdate on destruction (really the
+   destruction of the outermost instance).  This is used to prevent
+   flickering -- window implementations should only call wnoutrefresh,
+   and any time rendering is needed, an object of this type should be
+   instantiated.  */
 
-class tui_suppress_output
+class tui_batch_rendering
 {
 public:
 
-  tui_suppress_output ();
-  ~tui_suppress_output ();
+  tui_batch_rendering ();
+  ~tui_batch_rendering ();
 
-  DISABLE_COPY_AND_ASSIGN (tui_suppress_output);
+  DISABLE_COPY_AND_ASSIGN (tui_batch_rendering);
 
 private:
 
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index 80297e59dd6..a6c8c8d5866 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -343,7 +343,7 @@ tui_source_window_base::refresh_window ()
   int smincol = x + box_width () + left_margin;
   int smaxrow = sminrow + m_content.size () - 1;
   int smaxcol = smincol + view_width - 1;
-  prefresh (m_pad.get (), 0, pad_x, sminrow, smincol, smaxrow, smaxcol);
+  pnoutrefresh (m_pad.get (), 0, pad_x, sminrow, smincol, smaxrow, smaxcol);
 }
 
 void
diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
index 781ec85f8e8..bc96cd85d59 100644
--- a/gdb/tui/tui.c
+++ b/gdb/tui/tui.c
@@ -568,7 +568,7 @@ tui_disable_command (const char *args, int from_tty)
 void
 tui_show_assembly (struct gdbarch *gdbarch, CORE_ADDR addr)
 {
-  tui_suppress_output suppress;
+  tui_batch_rendering suppress;
   tui_add_win_to_layout (DISASSEM_WIN);
   tui_update_source_windows_with_addr (gdbarch, addr);
 }

-- 
2.44.0



More information about the Gdb-patches mailing list