From patchwork Fri Dec 27 23:50:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 37111 Received: (qmail 99032 invoked by alias); 27 Dec 2019 23:50:40 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 98938 invoked by uid 89); 27 Dec 2019 23:50:39 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=rendering, buffering, layout X-HELO: gateway24.websitewelcome.com Received: from gateway24.websitewelcome.com (HELO gateway24.websitewelcome.com) (192.185.51.228) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 27 Dec 2019 23:50:37 +0000 Received: from cm13.websitewelcome.com (cm13.websitewelcome.com [100.42.49.6]) by gateway24.websitewelcome.com (Postfix) with ESMTP id 2393D1F99 for ; Fri, 27 Dec 2019 17:50:36 -0600 (CST) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id kzNMihFx23Qi0kzNMiWvEU; Fri, 27 Dec 2019 17:50:36 -0600 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=mOC9Lmlgtq95suCNZz97qVuil1yN9zUr6I3NjTUDIZY=; b=JW9rc3wd4DKXXYG399o8CePYIF 5M1ahAR47q9FYJfNNDYPAh/5iPX9Edvk57tCAFLfTBB5LuNJCaJIt0q0mbDhbQ4Pz/0ptGLh0ELXE weBEje9+X5CetQ+rPjICIaCf8; Received: from 75-166-123-50.hlrn.qwest.net ([75.166.123.50]:38936 helo=bapiya.Home) by box5379.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92) (envelope-from ) id 1ikzNL-004GrV-Ua; Fri, 27 Dec 2019 16:50:36 -0700 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 3/3] Remove flickering from the TUI Date: Fri, 27 Dec 2019 16:50:34 -0700 Message-Id: <20191227235034.5453-4-tom@tromey.com> In-Reply-To: <20191227235034.5453-1-tom@tromey.com> References: <20191227235034.5453-1-tom@tromey.com> In some cases, the TUI flickers when redrawing. This can be seen mostly easily when switching layouts. This patch fixes the problem by exploiting the double buffering that curses already does. In some spots, the TUI will now disable flushing the curses buffers to the screen; and then flush them all at once when the rendering is complete. gdb/ChangeLog 2019-12-27 Tom Tromey * tui/tui.c (tui_show_assembly): Use tui_suppress_output. * tui/tui-wingeneral.h (class tui_suppress_output): New. (tui_wrefresh): Declare. * tui/tui-wingeneral.c (suppress_output): New global. (tui_suppress_output, ~tui_suppress_output): New constructor and destructor. (tui_wrefresh): New function. (tui_gen_win_info::refresh_window): Use tui_wrefresh. (tui_gen_win_info::make_window): Call wnoutrefresh when needed. * tui/tui-regs.h (struct tui_data_window) : Declare method. * tui/tui-regs.c (tui_data_window::erase_data_content): Call tui_wrefresh. (tui_data_window::no_refresh): New method. (tui_data_item_window::refresh_window): Call tui_wrefresh. (tui_reg_command): Use tui_suppress_output * tui/tui-layout.c (tui_set_layout): Use tui_suppress_output. * tui/tui-data.h (struct tui_gen_win_info) : New method. * tui/tui-command.c (tui_refresh_cmd_win): Call tui_wrefresh. Change-Id: Icb832ae100b861de3af3307488e636fa928d5c9f --- gdb/ChangeLog | 23 ++++++++++++++++++++ gdb/tui/tui-command.c | 2 +- gdb/tui/tui-data.h | 7 ++++++ gdb/tui/tui-layout.c | 2 ++ gdb/tui/tui-regs.c | 14 ++++++++++-- gdb/tui/tui-regs.h | 2 ++ gdb/tui/tui-wingeneral.c | 46 ++++++++++++++++++++++++++++++++++++++-- gdb/tui/tui-wingeneral.h | 23 ++++++++++++++++++++ gdb/tui/tui.c | 2 ++ 9 files changed, 116 insertions(+), 5 deletions(-) diff --git a/gdb/tui/tui-command.c b/gdb/tui/tui-command.c index 5f676b2e659..ca0e8f612bd 100644 --- a/gdb/tui/tui-command.c +++ b/gdb/tui/tui-command.c @@ -70,7 +70,7 @@ tui_refresh_cmd_win (void) { WINDOW *w = TUI_CMD_WIN->handle.get (); - wrefresh (w); + tui_wrefresh (w); /* FIXME: It's not clear why this is here. It was present in the original tui_puts code and is kept in order to diff --git a/gdb/tui/tui-data.h b/gdb/tui/tui-data.h index 2a822487fce..25a23860ef8 100644 --- a/gdb/tui/tui-data.h +++ b/gdb/tui/tui-data.h @@ -99,6 +99,13 @@ public: return handle != nullptr; } + /* Disable output until the next call to doupdate. */ + virtual void no_refresh () + { + if (handle != nullptr) + wnoutrefresh (handle.get ()); + } + /* Window handle. */ std::unique_ptr handle; /* Type of window. */ diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index bd2e6aee651..740178ca083 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -113,6 +113,8 @@ tui_set_layout (enum tui_layout_type layout_type) if (new_layout != cur_layout) { + tui_suppress_output suppress; + show_layout (new_layout); /* Now determine where focus should be. */ diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c index 85c7a31b0b6..cfcd80b7745 100644 --- a/gdb/tui/tui-regs.c +++ b/gdb/tui/tui-regs.c @@ -381,7 +381,7 @@ tui_data_window::erase_data_content (const char *prompt) x_pos = half_width - strlen (prompt); mvwaddstr (handle.get (), (height / 2), x_pos, (char *) prompt); } - wrefresh (handle.get ()); + tui_wrefresh (handle.get ()); } /* See tui-regs.h. */ @@ -434,6 +434,14 @@ tui_data_window::refresh_window () win.refresh_window (); } +void +tui_data_window::no_refresh () +{ + tui_gen_win_info::no_refresh (); + for (auto &&win : m_regs_content) + win.no_refresh (); +} + /* This function check all displayed registers for changes in values, given a particular frame. If the values have changed, they are updated with the new value and highlighted. */ @@ -502,7 +510,7 @@ tui_data_item_window::refresh_window () windows, which according to the ncurses man pages aren't well supported. */ touchwin (handle.get ()); - wrefresh (handle.get ()); + tui_wrefresh (handle.get ()); } } @@ -574,6 +582,8 @@ tui_reg_command (const char *args, int from_tty) /* 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-regs.h b/gdb/tui/tui-regs.h index 92df6183677..3ba4b28ddf6 100644 --- a/gdb/tui/tui-regs.h +++ b/gdb/tui/tui-regs.h @@ -70,6 +70,8 @@ struct tui_data_window : public tui_win_info void refresh_window () override; + void no_refresh () override; + const char *name () const override { return DATA_NAME; diff --git a/gdb/tui/tui-wingeneral.c b/gdb/tui/tui-wingeneral.c index 17be3e23e9a..091cd73986e 100644 --- a/gdb/tui/tui-wingeneral.c +++ b/gdb/tui/tui-wingeneral.c @@ -30,13 +30,51 @@ #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. */ + +static bool suppress_output; + +/* See tui-data.h. */ + +tui_suppress_output::tui_suppress_output () + : 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 () +{ + suppress_output = m_saved_suppress; + if (!suppress_output) + doupdate (); + + for (const auto &win : all_tui_windows ()) + win->refresh_window (); +} + +/* See tui-data.h. */ + +void +tui_wrefresh (WINDOW *win) +{ + if (!suppress_output) + wrefresh (win); +} + /* See tui-data.h. */ void tui_gen_win_info::refresh_window () { if (handle != NULL) - wrefresh (handle.get ()); + tui_wrefresh (handle.get ()); } /* Draw a border arround the window. */ @@ -133,7 +171,11 @@ tui_gen_win_info::make_window () { handle.reset (newwin (height, width, y, x)); if (handle != NULL) - scrollok (handle.get (), TRUE); + { + if (suppress_output) + wnoutrefresh (handle.get ()); + scrollok (handle.get (), TRUE); + } } void diff --git a/gdb/tui/tui-wingeneral.h b/gdb/tui/tui-wingeneral.h index 9995250ce9a..982a9364516 100644 --- a/gdb/tui/tui-wingeneral.h +++ b/gdb/tui/tui-wingeneral.h @@ -33,4 +33,27 @@ extern void tui_unhighlight_win (struct tui_win_info *); extern void tui_highlight_win (struct tui_win_info *); extern void tui_refresh_all (); +/* An RAII class that suppresses output on construction (calling + wnoutrefresh on the existing windows), and then flushes the output + (via doupdate) when destroyed. */ + +class tui_suppress_output +{ +public: + + tui_suppress_output (); + ~tui_suppress_output (); + + DISABLE_COPY_AND_ASSIGN (tui_suppress_output); + +private: + + /* Save the state of the suppression global. */ + bool m_saved_suppress; +}; + +/* Call wrefresh on the given window. However, if output is being + suppressed via tui_suppress_output, do not call wrefresh. */ +extern void tui_wrefresh (WINDOW *win); + #endif /* TUI_TUI_WINGENERAL_H */ diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c index 6fdfa4579f1..b0d31c3bc0c 100644 --- a/gdb/tui/tui.c +++ b/gdb/tui/tui.c @@ -30,6 +30,7 @@ #include "tui/tui-regs.h" #include "tui/tui-stack.h" #include "tui/tui-win.h" +#include "tui/tui-wingeneral.h" #include "tui/tui-winsource.h" #include "tui/tui-source.h" #include "target.h" @@ -575,6 +576,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_add_win_to_layout (DISASSEM_WIN); tui_update_source_windows_with_addr (gdbarch, addr); }