* [PATCH 0/7] TUI command changes, including new winwidth command @ 2022-01-28 15:55 Andrew Burgess 2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess ` (8 more replies) 0 siblings, 9 replies; 74+ messages in thread From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess I'm working on a patch to improve the TUI's window sizing and resizing behaviour. That's still a work in progress. But, as part of that work I needed to add support for resizing the width of a window. Given that we have horizontal window layout support, I think it makes sense to have this functionality whether or not I finish my bigger window resizing work. The highlights from this series are: 1. Add width information to 'info win' output, 2. Move some commands under the top-level 'tui' command, but add aliases so the old names still work, 3. Add a new 'winwidth' command. --- Andrew Burgess (7): gdb/tui: add window width information to 'info win' output gdb/doc: update docs for 'info win' and 'winheight' commands gdb: move some commands into the tui namespace gdb/tui: rename tui_layout_base::adjust_size to ::set_height gdb/tui: rename tui_layout_split:set_weights_from_heights gdb/testing/tui: add new functionality to tuiterm.exp gdb/tui: add new 'tui window width' command and 'winwidth' alias gdb/NEWS | 25 +++++ gdb/doc/gdb.texinfo | 43 ++++++--- gdb/testsuite/gdb.tui/info-win.exp | 61 ++++++++++++ gdb/testsuite/gdb.tui/winwidth.exp | 62 +++++++++++++ gdb/testsuite/lib/tuiterm.exp | 54 ++++++++++- gdb/tui/tui-layout.c | 50 +++++++--- gdb/tui/tui-layout.h | 115 +++++++++++++++++++++-- gdb/tui/tui-win.c | 143 +++++++++++++++++++++++++---- 8 files changed, 504 insertions(+), 49 deletions(-) create mode 100644 gdb/testsuite/gdb.tui/info-win.exp create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCH 1/7] gdb/tui: add window width information to 'info win' output 2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess @ 2022-01-28 15:55 ` Andrew Burgess 2022-01-28 17:00 ` Eli Zaretskii 2022-02-06 13:43 ` Andrew Burgess 2022-01-28 15:55 ` [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands Andrew Burgess ` (7 subsequent siblings) 8 siblings, 2 replies; 74+ messages in thread From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess Now that we support horizontal window placement in the tui, it makes sense to have 'info win' include the width, as well as the height, of the currently visible windows. That's what this commit does. Example output is now: (gdb) info win Name Lines Columns Focus src 12 40 (has focus) asm 12 41 status 1 80 cmd 11 80 I've added a NEWS entry, but the documentation was already suitably vague, it just says that 'info win' displays the size of the visible windows, so I don't think anything needs to be added there. I've also added some tests, as far as I could find, the 'info win' command was previously untested. --- gdb/NEWS | 4 ++ gdb/testsuite/gdb.tui/info-win.exp | 61 ++++++++++++++++++++++++++++++ gdb/tui/tui-win.c | 4 +- 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.tui/info-win.exp diff --git a/gdb/NEWS b/gdb/NEWS index e1900596ca7..8da68c88def 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -102,6 +102,10 @@ show debug lin-lwp debug linux-nat' and 'show debug linux-nat' should be used instead. +info win + This command now includes information about the width of the tui + windows in its output. + * Python API ** New function gdb.add_history(), which takes a gdb.Value object diff --git a/gdb/testsuite/gdb.tui/info-win.exp b/gdb/testsuite/gdb.tui/info-win.exp new file mode 100644 index 00000000000..2607d5be493 --- /dev/null +++ b/gdb/testsuite/gdb.tui/info-win.exp @@ -0,0 +1,61 @@ +# Copyright 2022 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test 'info win'. + +tuiterm_env + +standard_testfile + +Term::clean_restart 24 80 + +if {![Term::enter_tui]} { + unsupported "TUI not supported" + return +} + +Term::command "layout src" +Term::command "info win" +Term::check_region_contents "info win, layout src" \ + 0 16 80 8 [multi_line "info win\\s+" \ + "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \ + "src\\s+15\\s+80\\s+\\(has focus\\)\\s+" \ + "status\\s+1\\s+80\\s+" \ + "cmd\\s+8\\s+80\\s+"] + +Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1" +Term::command "layout h" +Term::command "winheight cmd + 3" + +# As the tuiterm.exp library just waits for the prompt and command to +# be echo'ed bcak to the screen, multiple 'info win' calls like this +# have a problem. Dejagnu will send the command to gdb, but will then +# immediately see the '(gdb) info win' output from the first use +# above. This means we end up rushing ahead, and some tests might +# fail. +# +# To work around this, I'm sending a unique command 'p 1' here, that +# only happens after the second 'info win' call. When the 'p 1' +# completes, I know the second 'info win' has also completed. +Term::command "info win" +Term::command "p 1" + +Term::check_region_contents "info win, layout h" \ + 0 13 80 11 [multi_line "info win\\s+" \ + "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \ + "src\\s+12\\s+40\\s+\\(has focus\\)\\s+" \ + "asm\\s+12\\s+41\\s+" \ + "status\\s+1\\s+80\\s+" \ + "cmd\\s+11\\s+80\\s+"] diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index c85dfd4e882..fd6ca59a728 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -714,9 +714,10 @@ tui_all_windows_info (const char *arg, int from_tty) struct tui_win_info *win_with_focus = tui_win_with_focus (); struct ui_out *uiout = current_uiout; - ui_out_emit_table table_emitter (uiout, 3, -1, "tui-windows"); + ui_out_emit_table table_emitter (uiout, 4, -1, "tui-windows"); uiout->table_header (10, ui_left, "name", "Name"); uiout->table_header (5, ui_right, "lines", "Lines"); + uiout->table_header (7, ui_right, "columns", "Columns"); uiout->table_header (10, ui_left, "focus", "Focus"); uiout->table_body (); @@ -727,6 +728,7 @@ tui_all_windows_info (const char *arg, int from_tty) uiout->field_string ("name", win_info->name ()); uiout->field_signed ("lines", win_info->height); + uiout->field_signed ("columns", win_info->width); if (win_with_focus == win_info) uiout->field_string ("focus", _("(has focus)")); else -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCH 1/7] gdb/tui: add window width information to 'info win' output 2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess @ 2022-01-28 17:00 ` Eli Zaretskii 2022-02-06 13:43 ` Andrew Burgess 1 sibling, 0 replies; 74+ messages in thread From: Eli Zaretskii @ 2022-01-28 17:00 UTC (permalink / raw) To: Andrew Burgess; +Cc: gdb-patches > Date: Fri, 28 Jan 2022 15:55:02 +0000 > From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> > Cc: Andrew Burgess <aburgess@redhat.com> > > diff --git a/gdb/NEWS b/gdb/NEWS > index e1900596ca7..8da68c88def 100644 > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -102,6 +102,10 @@ show debug lin-lwp > debug linux-nat' and 'show debug linux-nat' should be used > instead. > > +info win > + This command now includes information about the width of the tui > + windows in its output. > + This part is OK, thanks. ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCH 1/7] gdb/tui: add window width information to 'info win' output 2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess 2022-01-28 17:00 ` Eli Zaretskii @ 2022-02-06 13:43 ` Andrew Burgess 1 sibling, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 13:43 UTC (permalink / raw) To: gdb-patches * Andrew Burgess <aburgess@redhat.com> [2022-01-28 15:55:02 +0000]: > Now that we support horizontal window placement in the tui, it makes > sense to have 'info win' include the width, as well as the height, of > the currently visible windows. > > That's what this commit does. Example output is now: > > (gdb) info win > Name Lines Columns Focus > src 12 40 (has focus) > asm 12 41 > status 1 80 > cmd 11 80 > > I've added a NEWS entry, but the documentation was already suitably > vague, it just says that 'info win' displays the size of the visible > windows, so I don't think anything needs to be added there. > > I've also added some tests, as far as I could find, the 'info win' > command was previously untested. I've gone ahead and pushed this patch, I think this is the obvious solution for adding this information to gdb. If anyone disagrees, feel free to say. Thanks, Andrew > --- > gdb/NEWS | 4 ++ > gdb/testsuite/gdb.tui/info-win.exp | 61 ++++++++++++++++++++++++++++++ > gdb/tui/tui-win.c | 4 +- > 3 files changed, 68 insertions(+), 1 deletion(-) > create mode 100644 gdb/testsuite/gdb.tui/info-win.exp > > diff --git a/gdb/NEWS b/gdb/NEWS > index e1900596ca7..8da68c88def 100644 > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -102,6 +102,10 @@ show debug lin-lwp > debug linux-nat' and 'show debug linux-nat' should be used > instead. > > +info win > + This command now includes information about the width of the tui > + windows in its output. > + > * Python API > > ** New function gdb.add_history(), which takes a gdb.Value object > diff --git a/gdb/testsuite/gdb.tui/info-win.exp b/gdb/testsuite/gdb.tui/info-win.exp > new file mode 100644 > index 00000000000..2607d5be493 > --- /dev/null > +++ b/gdb/testsuite/gdb.tui/info-win.exp > @@ -0,0 +1,61 @@ > +# Copyright 2022 Free Software Foundation, Inc. > + > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program. If not, see <http://www.gnu.org/licenses/>. > + > +# Test 'info win'. > + > +tuiterm_env > + > +standard_testfile > + > +Term::clean_restart 24 80 > + > +if {![Term::enter_tui]} { > + unsupported "TUI not supported" > + return > +} > + > +Term::command "layout src" > +Term::command "info win" > +Term::check_region_contents "info win, layout src" \ > + 0 16 80 8 [multi_line "info win\\s+" \ > + "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \ > + "src\\s+15\\s+80\\s+\\(has focus\\)\\s+" \ > + "status\\s+1\\s+80\\s+" \ > + "cmd\\s+8\\s+80\\s+"] > + > +Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1" > +Term::command "layout h" > +Term::command "winheight cmd + 3" > + > +# As the tuiterm.exp library just waits for the prompt and command to > +# be echo'ed bcak to the screen, multiple 'info win' calls like this > +# have a problem. Dejagnu will send the command to gdb, but will then > +# immediately see the '(gdb) info win' output from the first use > +# above. This means we end up rushing ahead, and some tests might > +# fail. > +# > +# To work around this, I'm sending a unique command 'p 1' here, that > +# only happens after the second 'info win' call. When the 'p 1' > +# completes, I know the second 'info win' has also completed. > +Term::command "info win" > +Term::command "p 1" > + > +Term::check_region_contents "info win, layout h" \ > + 0 13 80 11 [multi_line "info win\\s+" \ > + "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \ > + "src\\s+12\\s+40\\s+\\(has focus\\)\\s+" \ > + "asm\\s+12\\s+41\\s+" \ > + "status\\s+1\\s+80\\s+" \ > + "cmd\\s+11\\s+80\\s+"] > diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c > index c85dfd4e882..fd6ca59a728 100644 > --- a/gdb/tui/tui-win.c > +++ b/gdb/tui/tui-win.c > @@ -714,9 +714,10 @@ tui_all_windows_info (const char *arg, int from_tty) > struct tui_win_info *win_with_focus = tui_win_with_focus (); > struct ui_out *uiout = current_uiout; > > - ui_out_emit_table table_emitter (uiout, 3, -1, "tui-windows"); > + ui_out_emit_table table_emitter (uiout, 4, -1, "tui-windows"); > uiout->table_header (10, ui_left, "name", "Name"); > uiout->table_header (5, ui_right, "lines", "Lines"); > + uiout->table_header (7, ui_right, "columns", "Columns"); > uiout->table_header (10, ui_left, "focus", "Focus"); > uiout->table_body (); > > @@ -727,6 +728,7 @@ tui_all_windows_info (const char *arg, int from_tty) > > uiout->field_string ("name", win_info->name ()); > uiout->field_signed ("lines", win_info->height); > + uiout->field_signed ("columns", win_info->width); > if (win_with_focus == win_info) > uiout->field_string ("focus", _("(has focus)")); > else > -- > 2.25.4 > ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands 2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess 2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess @ 2022-01-28 15:55 ` Andrew Burgess 2022-01-28 17:03 ` Eli Zaretskii 2022-01-28 15:55 ` [PATCH 3/7] gdb: move some commands into the tui namespace Andrew Burgess ` (6 subsequent siblings) 8 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This started by noticing that the docs for 'winheight' are out of date, the docs currently give a specific list of possible window names. However, now that windows can be implemented in Python, it is not possible to list all possible names. I now link the user to a mechanism by which they can discover the valid names for themselves at run time (by using 'info win'). That, and the fact that gdb provides tab-completion of the name at the command line, feels good enough. Finally, I noticed that the docs for 'win info' don't explicitly say that the name of the window is given in the output. This could probably have been inferred, but given I'm now linking to this as a mechanism to find the window name, I'd prefer to mention that the name can be found in the output. --- gdb/doc/gdb.texinfo | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index fe81687a66c..e72fa4aaaae 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -28812,9 +28812,10 @@ @kindex tui disable Disable TUI mode, returning to the console interpreter. +@anchor{info_win_command} @item info win @kindex info win -List and give the size of all displayed windows. +List the names and sizes of all currently displayed windows. @item tui new-layout @var{name} @var{window} @var{weight} @r{[}@var{window} @var{weight}@dots{}@r{]} @kindex tui new-layout @@ -28961,11 +28962,11 @@ @item winheight @var{name} +@var{count} @itemx winheight @var{name} -@var{count} @kindex winheight -Change the height of the window @var{name} by @var{count} -lines. Positive counts increase the height, while negative counts -decrease it. The @var{name} parameter can be one of @code{src} (the -source window), @code{cmd} (the command window), @code{asm} (the -disassembly window), or @code{regs} (the register display window). +Change the height of the window @var{name} by @var{count} lines. +Positive counts increase the height, while negative counts decrease +it. The @var{name} parameter can be the name of any currently visible +window. The names of the currently visible windows can be discovered +using @code{info win} (@pxref{info_win_command,,info win}). @end table @node TUI Configuration -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands 2022-01-28 15:55 ` [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands Andrew Burgess @ 2022-01-28 17:03 ` Eli Zaretskii 2022-02-06 13:43 ` Andrew Burgess 0 siblings, 1 reply; 74+ messages in thread From: Eli Zaretskii @ 2022-01-28 17:03 UTC (permalink / raw) To: Andrew Burgess; +Cc: gdb-patches > Date: Fri, 28 Jan 2022 15:55:03 +0000 > From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> > Cc: Andrew Burgess <aburgess@redhat.com> > > gdb/doc/gdb.texinfo | 13 +++++++------ > 1 file changed, 7 insertions(+), 6 deletions(-) > > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > index fe81687a66c..e72fa4aaaae 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo This is okay, but... > +Change the height of the window @var{name} by @var{count} lines. > +Positive counts increase the height, while negative counts decrease > +it. The @var{name} parameter can be the name of any currently visible > +window. The names of the currently visible windows can be discovered > +using @code{info win} (@pxref{info_win_command,,info win}). ^^^^^ Please use @kbd there, not @code. ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands 2022-01-28 17:03 ` Eli Zaretskii @ 2022-02-06 13:43 ` Andrew Burgess 0 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 13:43 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches * Eli Zaretskii via Gdb-patches <gdb-patches@sourceware.org> [2022-01-28 19:03:21 +0200]: > > Date: Fri, 28 Jan 2022 15:55:03 +0000 > > From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> > > Cc: Andrew Burgess <aburgess@redhat.com> > > > > gdb/doc/gdb.texinfo | 13 +++++++------ > > 1 file changed, 7 insertions(+), 6 deletions(-) > > > > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > > index fe81687a66c..e72fa4aaaae 100644 > > --- a/gdb/doc/gdb.texinfo > > +++ b/gdb/doc/gdb.texinfo > > This is okay, but... > > > +Change the height of the window @var{name} by @var{count} lines. > > +Positive counts increase the height, while negative counts decrease > > +it. The @var{name} parameter can be the name of any currently visible > > +window. The names of the currently visible windows can be discovered > > +using @code{info win} (@pxref{info_win_command,,info win}). > ^^^^^ > Please use @kbd there, not @code. Thanks, I made this fix, and pushed this patch. Andrew ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCH 3/7] gdb: move some commands into the tui namespace 2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess 2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess 2022-01-28 15:55 ` [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands Andrew Burgess @ 2022-01-28 15:55 ` Andrew Burgess 2022-01-28 17:04 ` Eli Zaretskii 2022-01-28 15:55 ` [PATCH 4/7] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess ` (5 subsequent siblings) 8 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess There are a lot of tui related commands that live in the top-level command name space, e.g. layout, focus, refresh, winheight. Having them at the top level means less typing for the user, which is good, but, I think, makes command discovery harder. In this commit, I propose moving all of the above mentioned commands into the tui namespace, so 'layout' becomes 'tui layout', etc. But I will then add aliases so that the old commands will still work, e.g. I'll make 'layout' an alias for 'tui layout'. The benefit I see in this work is that tui related commands can be more easily discovered by typing 'tui ' and then tab-completing. Also the "official" command is now a tui-sub-command, this is visible in, for example, the help output, e.g.: (gdb) help layout tui layout, layout Change the layout of windows. Usage: tui layout prev | next | LAYOUT-NAME List of tui layout subcommands: tui layout asm -- Apply the "asm" layout. tui layout next -- Apply the next TUI layout. tui layout prev -- Apply the previous TUI layout. tui layout regs -- Apply the TUI register layout. tui layout split -- Apply the "split" layout. tui layout src -- Apply the "src" layout. Which I think is a good thing, it makes it clearer that this is a tui command. I've added a NEWS entry and updated the docs to mention the new and old command names, with the new name being mentioned first. --- gdb/NEWS | 15 +++++++++++++++ gdb/doc/gdb.texinfo | 18 +++++++++++++----- gdb/tui/tui-layout.c | 16 +++++++++++++--- gdb/tui/tui-win.c | 40 ++++++++++++++++++++++++++++++++-------- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 8da68c88def..f97f643b6ee 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -81,6 +81,14 @@ maint show gnu-source-highlight enabled styling to a particular source file, then the Python Pygments library will be used instead. +tui layout +tui focus +tui refresh +tui window height + These are the new names for the old 'layout', 'focus', 'refresh', + and 'winheight' tui commands respectively. The old names still + exist as aliases to these new commands. + * Changed commands maint packet @@ -106,6 +114,13 @@ info win This command now includes information about the width of the tui windows in its output. +layout +focus +refresh +winheight + These commands are now aliases for the 'tui layout', 'tui focus', + 'tui refresh', and 'tui window height' commands respectively. + * Python API ** New function gdb.add_history(), which takes a gdb.Value object diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index e72fa4aaaae..df35887a304 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -28866,8 +28866,10 @@ width of the terminal. Because they have weight 2, the source and assembly windows will be twice the height of the command window. -@item layout @var{name} +@kindex tui layout @kindex layout +@item tui layout @var{name} +@itemx layout @var{name} Changes which TUI windows are displayed. The @var{name} parameter controls which layout is shown. It can be either one of the built-in layout names, or the name of a layout defined by the user using @@ -28897,8 +28899,9 @@ register, assembler, and command windows. @end table -@item focus @var{name} @kindex focus +@item tui focus @var{name} +@itemx focus @var{name} Changes which TUI window is currently active for scrolling. The @var{name} parameter can be any of the following: @@ -28922,8 +28925,10 @@ Make the command window active for scrolling. @end table -@item refresh +@kindex tui refresh @kindex refresh +@item tui refresh +@itemx refresh Refresh the screen. This is similar to typing @kbd{C-L}. @item tui reg @var{group} @@ -28959,9 +28964,12 @@ @kindex update Update the source window and the current execution point. -@item winheight @var{name} +@var{count} -@itemx winheight @var{name} -@var{count} +@kindex tui window height @kindex winheight +@item tui window height @var{name} +@var{count} +@itemx tui window height @var{name} -@var{count} +@itemx winheight @var{name} +@var{count} +@itemx winheight @var{name} -@var{count} Change the height of the window @var{name} by @var{count} lines. Positive counts increase the height, while negative counts decrease it. The @var{name} parameter can be the name of any currently visible diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index cef9190c3e1..f8388e3fca5 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -839,6 +839,14 @@ destroy_layout (struct cmd_list_element *self, void *context) static struct cmd_list_element *layout_list; +/* Called to implement 'tui layout'. */ + +static void +tui_layout_command (const char *args, int from_tty) +{ + help_list (layout_list, "tui layout ", all_commands, gdb_stdout); +} + /* Add a "layout" command with name NAME that switches to LAYOUT. */ static struct cmd_list_element * @@ -1017,10 +1025,12 @@ void _initialize_tui_layout (); void _initialize_tui_layout () { - add_basic_prefix_cmd ("layout", class_tui, _("\ + struct cmd_list_element *layout_cmd + = add_prefix_cmd ("layout", class_tui, tui_layout_command, _("\ Change the layout of windows.\n\ -Usage: layout prev | next | LAYOUT-NAME"), - &layout_list, 0, &cmdlist); +Usage: tui layout prev | next | LAYOUT-NAME"), + &layout_list, 0, tui_get_cmd_list ()); + add_com_alias ("layout", layout_cmd, class_tui, 0); add_cmd ("next", class_tui, tui_next_layout_command, _("Apply the next TUI layout."), diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index fd6ca59a728..ba6aca3d078 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -977,6 +977,18 @@ parse_scrolling_args (const char *arg, } } +/* The list of 'tui window' sub-commands. */ + +static cmd_list_element *tui_window_cmds = nullptr; + +/* Called to implement 'tui window'. */ + +static void +tui_window_command (const char *args, int from_tty) +{ + help_list (tui_window_cmds, "tui window ", all_commands, gdb_stdout); +} + /* Function to initialize gdb commands, for tui window manipulation. */ @@ -995,8 +1007,11 @@ _initialize_tui_win () &tui_setlist, &tui_showlist, &setlist, &showlist); - add_com ("refresh", class_tui, tui_refresh_all_command, - _("Refresh the terminal display.")); + cmd_list_element *refresh_cmd + = add_cmd ("refresh", class_tui, tui_refresh_all_command, + _("Refresh the terminal display."), + tui_get_cmd_list ()); + add_com_alias ("refresh", refresh_cmd, class_tui, 0); cmd_list_element *tabset_cmd = add_com ("tabset", class_tui, tui_set_tab_width_command, _("\ @@ -1004,21 +1019,30 @@ Set the width (in characters) of tab stops.\n\ Usage: tabset N")); deprecate_cmd (tabset_cmd, "set tui tab-width"); + /* Setup the 'tui window' list of command. */ + add_prefix_cmd ("window", class_tui, tui_window_command, + _("Text User Interface window commands."), + &tui_window_cmds, 1, tui_get_cmd_list ()); + cmd_list_element *winheight_cmd - = add_com ("winheight", class_tui, tui_set_win_height_command, _("\ + = add_cmd ("height", class_tui, tui_set_win_height_command, _("\ Set or modify the height of a specified window.\n\ -Usage: winheight WINDOW-NAME [+ | -] NUM-LINES\n\ -Use \"info win\" to see the names of the windows currently being displayed.")); +Usage: tui window height WINDOW-NAME [+ | -] NUM-LINES\n\ +Use \"info win\" to see the names of the windows currently being displayed."), + &tui_window_cmds); + add_com_alias ("winheight", winheight_cmd, class_tui, 0); add_com_alias ("wh", winheight_cmd, class_tui, 0); set_cmd_completer (winheight_cmd, winheight_completer); add_info ("win", tui_all_windows_info, _("List of all displayed windows.\n\ Usage: info win")); cmd_list_element *focus_cmd - = add_com ("focus", class_tui, tui_set_focus_command, _("\ + = add_cmd ("focus", class_tui, tui_set_focus_command, _("\ Set focus to named window or next/prev window.\n\ -Usage: focus [WINDOW-NAME | next | prev]\n\ -Use \"info win\" to see the names of the windows currently being displayed.")); +Usage: tui focus [WINDOW-NAME | next | prev]\n\ +Use \"info win\" to see the names of the windows currently being displayed."), + tui_get_cmd_list ()); + add_com_alias ("focus", focus_cmd, class_tui, 0); add_com_alias ("fs", focus_cmd, class_tui, 0); set_cmd_completer (focus_cmd, focus_completer); add_com ("+", class_tui, tui_scroll_forward_command, _("\ -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCH 3/7] gdb: move some commands into the tui namespace 2022-01-28 15:55 ` [PATCH 3/7] gdb: move some commands into the tui namespace Andrew Burgess @ 2022-01-28 17:04 ` Eli Zaretskii 0 siblings, 0 replies; 74+ messages in thread From: Eli Zaretskii @ 2022-01-28 17:04 UTC (permalink / raw) To: Andrew Burgess; +Cc: gdb-patches > Date: Fri, 28 Jan 2022 15:55:04 +0000 > From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> > Cc: Andrew Burgess <aburgess@redhat.com> > > gdb/NEWS | 15 +++++++++++++++ > gdb/doc/gdb.texinfo | 18 +++++++++++++----- > gdb/tui/tui-layout.c | 16 +++++++++++++--- > gdb/tui/tui-win.c | 40 ++++++++++++++++++++++++++++++++-------- > 4 files changed, 73 insertions(+), 16 deletions(-) Thanks, the documentation parts are OK. ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCH 4/7] gdb/tui: rename tui_layout_base::adjust_size to ::set_height 2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess ` (2 preceding siblings ...) 2022-01-28 15:55 ` [PATCH 3/7] gdb: move some commands into the tui namespace Andrew Burgess @ 2022-01-28 15:55 ` Andrew Burgess 2022-01-28 15:55 ` [PATCH 5/7] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess ` (4 subsequent siblings) 8 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess Rename tui_layout_base::adjust_size to tui_layout_base::set_height, the new name more accurately reflects what this member function does, and makes it easier for a later commit to add a new tui_layout_base::set_width member function. There should be no user visible changes after this commit. --- gdb/tui/tui-layout.c | 6 +++--- gdb/tui/tui-layout.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index f8388e3fca5..4c355c79d65 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -118,7 +118,7 @@ tui_apply_current_layout () void tui_adjust_window_height (struct tui_win_info *win, int new_height) { - applied_layout->adjust_size (win->name (), new_height); + applied_layout->set_height (win->name (), new_height); } /* Set the current layout to LAYOUT. */ @@ -570,7 +570,7 @@ tui_layout_split::set_weights_from_heights () /* See tui-layout.h. */ tui_adjust_result -tui_layout_split::adjust_size (const char *name, int new_height) +tui_layout_split::set_height (const char *name, int new_height) { /* Look through the children. If one is a layout holding the named window, we're done; or if one actually is the named window, @@ -579,7 +579,7 @@ tui_layout_split::adjust_size (const char *name, int new_height) for (int i = 0; i < m_splits.size (); ++i) { tui_adjust_result adjusted - = m_splits[i].layout->adjust_size (name, new_height); + = m_splits[i].layout->set_height (name, new_height); if (adjusted == HANDLED) return HANDLED; if (adjusted == FOUND) diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index b9a5d9b898d..acea7ac8f64 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -75,9 +75,9 @@ class tui_layout_base return nullptr; } - /* Adjust the size of the window named NAME to NEW_HEIGHT, updating + /* Set the height of the window named NAME to NEW_HEIGHT, updating the sizes of the other windows around it. */ - virtual tui_adjust_result adjust_size (const char *name, int new_height) = 0; + virtual tui_adjust_result set_height (const char *name, int new_height) = 0; /* Remove some windows from the layout, leaving the command window and the window being passed in here. */ @@ -127,7 +127,7 @@ class tui_layout_window : public tui_layout_base return m_contents.c_str (); } - tui_adjust_result adjust_size (const char *name, int new_height) override + tui_adjust_result set_height (const char *name, int new_height) override { return m_contents == name ? FOUND : NOT_FOUND; } @@ -192,7 +192,7 @@ class tui_layout_split : public tui_layout_base void apply (int x, int y, int width, int height) override; - tui_adjust_result adjust_size (const char *name, int new_height) override; + tui_adjust_result set_height (const char *name, int new_height) override; bool top_boxed_p () const override; -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCH 5/7] gdb/tui: rename tui_layout_split:set_weights_from_heights 2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess ` (3 preceding siblings ...) 2022-01-28 15:55 ` [PATCH 4/7] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess @ 2022-01-28 15:55 ` Andrew Burgess 2022-01-28 15:55 ` [PATCH 6/7] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess ` (3 subsequent siblings) 8 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess In a following commit I'm going to add the ability to change the width of a tui window (when in a horizontal layout). As a result, some of the places where we currently hard-code references to height need to be changed to handle either height, or width, based on whether we are in a vertical, or horizontal layout. This commit renames set_weights_from_heights to set_weights_from_sizes, and makes the function use either the height, or width as appropriate. Currently, the only place that we call this function is from the tui_layout_split::set_height function, in a part of the code we will only reach for vertical layouts, so the new code is not actually being used, but, this small change will help make later patches smaller, so I'm proposing this as a stand alone change. There should be no user visible changes after this commit. --- gdb/tui/tui-layout.c | 9 +++++---- gdb/tui/tui-layout.h | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 4c355c79d65..9e856ccf3fa 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -561,10 +561,11 @@ tui_layout_split::bottom_boxed_p () const /* See tui-layout.h. */ void -tui_layout_split::set_weights_from_heights () +tui_layout_split::set_weights_from_sizes () { for (int i = 0; i < m_splits.size (); ++i) - m_splits[i].weight = m_splits[i].layout->height; + m_splits[i].weight + = m_vertical ? m_splits[i].layout->height : m_splits[i].layout->width; } /* See tui-layout.h. */ @@ -596,7 +597,7 @@ tui_layout_split::set_height (const char *name, int new_height) if (m_splits[found_index].layout->height == new_height) return HANDLED; - set_weights_from_heights (); + set_weights_from_sizes (); int delta = m_splits[found_index].weight - new_height; m_splits[found_index].weight = new_height; @@ -634,7 +635,7 @@ tui_layout_split::set_height (const char *name, int new_height) { warning (_("Invalid window height specified")); /* Effectively undo any modifications made here. */ - set_weights_from_heights (); + set_weights_from_sizes (); } else { diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index acea7ac8f64..8f41835b94c 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -217,8 +217,9 @@ class tui_layout_split : public tui_layout_base private: - /* Set the weights from the current heights. */ - void set_weights_from_heights (); + /* Set the weights from the current heights (when m_vertical is true) or + widths (when m_vertical is false). */ + void set_weights_from_sizes (); struct split { -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCH 6/7] gdb/testing/tui: add new functionality to tuiterm.exp 2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess ` (4 preceding siblings ...) 2022-01-28 15:55 ` [PATCH 5/7] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess @ 2022-01-28 15:55 ` Andrew Burgess 2022-01-28 15:55 ` [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess ` (2 subsequent siblings) 8 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess While working on the next patch in this series, I was sending additional commands to the terminal with Term::command. There was nothing special about these commands, just normal "print EXPRESSION" type things, but I clearly poked ncurses in just the right way so that it started sending two previously unseen control sequences, 'Insert Line' and 'Delete Characters'. Now, the Term::command calls I added above were only done to help be debug the test, without them, these two control sequences are not triggered. But, given I've gone to the effort of adding these features to tuiterm.exp, I figure I might as well share this work. Additionally, I noticed a bug in 'Erase in Line' that this commit fixes; in mode 1 the erase should be from the start of the line through to the cursor, not to the character before the cursor. This bug would mean that random characters would sometimes be left in the terminal output. --- gdb/testsuite/lib/tuiterm.exp | 54 ++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp index 38948015e96..f2be3394db0 100644 --- a/gdb/testsuite/lib/tuiterm.exp +++ b/gdb/testsuite/lib/tuiterm.exp @@ -317,13 +317,40 @@ namespace eval Term { # From cursor to end. _clear_in_line $_cur_col $_cols $_cur_row } elseif {$arg == 1} { - _clear_in_line 0 $_cur_col $_cur_row + _clear_in_line 0 [expr $_cur_col + 1] $_cur_row } elseif {$arg == 2} { _clear_in_line 0 $_cols $_cur_row } } } + # Insert Line + # + # https://vt100.net/docs/vt510-rm/IL.html + proc _csi_L {args} { + set arg [_default [lindex $args 0] 1] + + _log_cur "Insert Line ($arg)" { + variable _cur_col + variable _cur_row + variable _rows + variable _cols + variable _chars + + set y [expr $_rows - 2] + set next_y [expr $y + 1] + while {$y >= $_cur_row} { + for {set x 0} {$x < $_cols} {incr x} { + set _chars($x,$next_y) $_chars($x,$y) + } + incr y -1 + incr next_y -1 + } + + _clear_lines $_cur_row $_rows + } + } + # Delete line. # # https://vt100.net/docs/vt510-rm/DL.html @@ -349,6 +376,31 @@ namespace eval Term { } } + # Delete Characters + # + # https://vt100.net/docs/vt510-rm/DCH.html + proc _csi_P {args} { + set count [_default [lindex $args 0] 1] + + _log_cur "Delete Character ($count)" { + variable _cur_col + variable _cur_row + variable _cols + variable _chars + + set dx [expr $_cur_col + 1] + set sx [expr $_cur_col + 1 + $count] + set y $_cur_row + + while {$sx < $_cols} { + set _chars($dx,$y) $_chars($sx,$y) + incr sx + incr dx + } + _clear_in_line $dx $sx $y + } + } + # Erase chars. # # https://vt100.net/docs/vt510-rm/ECH.html -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias 2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess ` (5 preceding siblings ...) 2022-01-28 15:55 ` [PATCH 6/7] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess @ 2022-01-28 15:55 ` Andrew Burgess 2022-01-28 17:05 ` Eli Zaretskii 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess 2022-03-04 17:23 ` [PATCH 0/7] TUI command changes, including new winwidth command Tom Tromey 8 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-01-28 15:55 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit adds a new command 'tui window width', and an alias 'winwidth'. This command is equivalent to the old 'winheight' command (which was recently renamed 'tui window height'). Even though I recently moved the old tui commands under the tui namespace, and I would strongly encourage all new tui commands to be added as 'tui ....' only (users can create their own top-level aliases if they want), I'm breaking that suggestion here, and adding a 'winwidth' alias. Given that we already have 'winheight' and have done for years, it just didn't seem right to no have the matching 'winwidth'. You might notice in the test that the window resizing doesn't quite work right. I setup a horizontal layout, then grow and shrink the windows. At the end of the test the windows should be back to their original size... ... they are not. This isn't my fault, honest! GDB's window resizing is a little ... temperamental, and is prone to getting things slightly wrong during resizes, off by 1 type things. This is true for height resizing, as well as the new width resizing. I'm currently working on a patch to improve the resizing algorithm, which should improve things in this area. For now, I'm happy that the width resizing is as good as the height resizing, given the existing quirks. As for the changes in gdb itself, I've mostly just templated the existing height adjustment code so that the two functions tui_layout_split::adjust_size (tui-layout.c) and tui_set_win_height_command (tui-win.c) now have a template parameter "policy", this policy allows me to specialise the functions for either width or height adjustment. Function arguments, and locals, are renamed, replacing 'height' with 'size'. --- gdb/NEWS | 6 ++ gdb/doc/gdb.texinfo | 12 ++++ gdb/testsuite/gdb.tui/winwidth.exp | 62 +++++++++++++++++ gdb/tui/tui-layout.c | 23 +++++-- gdb/tui/tui-layout.h | 104 ++++++++++++++++++++++++++++- gdb/tui/tui-win.c | 99 +++++++++++++++++++++++++-- 6 files changed, 291 insertions(+), 15 deletions(-) create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp diff --git a/gdb/NEWS b/gdb/NEWS index f97f643b6ee..1faef78056a 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -89,6 +89,12 @@ tui window height and 'winheight' tui commands respectively. The old names still exist as aliases to these new commands. +tui window width +winwidth + The new command 'tui window width', and the alias 'winwidth' allow + the width of a tui window to be adjusted when windows are laid out + in horizontal mode. + * Changed commands maint packet diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index df35887a304..cb5cfbaefc1 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -28975,6 +28975,18 @@ it. The @var{name} parameter can be the name of any currently visible window. The names of the currently visible windows can be discovered using @code{info win} (@pxref{info_win_command,,info win}). + +@kindex tui window width +@kindex winwidth +@item tui window width @var{name} +@var{count} +@itemx tui window width @var{name} -@var{count} +@itemx winwidth @var{name} +@var{count} +@itemx winwidth @var{name} -@var{count} +Change the width of the window @var{name} by @var{count} columns. +Positive counts increase the width, while negative counts decrease it. +The @var{name} parameter can be the name of any currently visible +window. The names of the currently visible windows can be discovered +using @code{info win} (@pxref{info_win_command,,info win}). @end table @node TUI Configuration diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp new file mode 100644 index 00000000000..b0a838b578f --- /dev/null +++ b/gdb/testsuite/gdb.tui/winwidth.exp @@ -0,0 +1,62 @@ +# Copyright 2022 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test the "winwidth" command. + +tuiterm_env + +standard_testfile tui-layout.c + +if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} { + return -1 +} + +Term::clean_restart 24 80 $testfile +if {![Term::enter_tui]} { + unsupported "TUI not supported" + return +} + +Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1" +Term::command "layout h" + +with_test_prefix "original window sizes" { + Term::check_box "source box" 0 0 40 15 + Term::check_box "asm box" 39 0 41 15 + Term::command "winwidth src +5" +} + +with_test_prefix "after src +5" { + Term::check_box "source box" 0 0 44 15 + Term::check_box "asm box" 43 0 37 15 + Term::command "winwidth asm -5" +} + +with_test_prefix "after asm -5" { + Term::check_box "source box" 0 0 48 15 + Term::check_box "asm box" 47 0 33 15 + Term::command "winwidth asm +8" +} + +with_test_prefix "after asm +8" { + Term::check_box "source box" 0 0 39 15 + Term::check_box "asm box" 38 0 42 15 + Term::command "winwidth src -2" +} + +with_test_prefix "after src -2" { + Term::check_box "source box" 0 0 36 15 + Term::check_box "asm box" 35 0 45 15 +} diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 9e856ccf3fa..13e4d462426 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -121,6 +121,14 @@ tui_adjust_window_height (struct tui_win_info *win, int new_height) applied_layout->set_height (win->name (), new_height); } +/* See tui-layout. */ + +void +tui_adjust_window_width (struct tui_win_info *win, int new_width) +{ + applied_layout->set_width (win->name (), new_width); +} + /* Set the current layout to LAYOUT. */ static void @@ -570,8 +578,9 @@ tui_layout_split::set_weights_from_sizes () /* See tui-layout.h. */ +template<class Policy> tui_adjust_result -tui_layout_split::set_height (const char *name, int new_height) +tui_layout_split::set_size (const char *name, int new_size) { /* Look through the children. If one is a layout holding the named window, we're done; or if one actually is the named window, @@ -580,12 +589,12 @@ tui_layout_split::set_height (const char *name, int new_height) for (int i = 0; i < m_splits.size (); ++i) { tui_adjust_result adjusted - = m_splits[i].layout->set_height (name, new_height); + = Policy::set_size (m_splits[i].layout, name, new_size); if (adjusted == HANDLED) return HANDLED; if (adjusted == FOUND) { - if (!m_vertical) + if (!Policy::can_adjust (this)) return FOUND; found_index = i; break; @@ -594,12 +603,12 @@ tui_layout_split::set_height (const char *name, int new_height) if (found_index == -1) return NOT_FOUND; - if (m_splits[found_index].layout->height == new_height) + if (Policy::current_size (m_splits[found_index].layout) == new_size) return HANDLED; set_weights_from_sizes (); - int delta = m_splits[found_index].weight - new_height; - m_splits[found_index].weight = new_height; + int delta = m_splits[found_index].weight - new_size; + m_splits[found_index].weight = new_size; /* Distribute the "delta" over the next window; but if the next window cannot hold it all, keep going until we either find a @@ -633,7 +642,7 @@ tui_layout_split::set_height (const char *name, int new_height) if (delta != 0) { - warning (_("Invalid window height specified")); + Policy::invalid_size_warning (); /* Effectively undo any modifications made here. */ set_weights_from_sizes (); } diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index 8f41835b94c..f4ef0895f1f 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -79,6 +79,10 @@ class tui_layout_base the sizes of the other windows around it. */ virtual tui_adjust_result set_height (const char *name, int new_height) = 0; + /* Set the width of the window named NAME to NEW_WIDTH, updating + the sizes of the other windows around it. */ + virtual tui_adjust_result set_width (const char *name, int new_width) = 0; + /* Remove some windows from the layout, leaving the command window and the window being passed in here. */ virtual void remove_windows (const char *name) = 0; @@ -132,6 +136,11 @@ class tui_layout_window : public tui_layout_base return m_contents == name ? FOUND : NOT_FOUND; } + tui_adjust_result set_width (const char *name, int new_width) override + { + return m_contents == name ? FOUND : NOT_FOUND; + } + bool top_boxed_p () const override; bool bottom_boxed_p () const override; @@ -192,7 +201,15 @@ class tui_layout_split : public tui_layout_base void apply (int x, int y, int width, int height) override; - tui_adjust_result set_height (const char *name, int new_height) override; + tui_adjust_result set_height (const char *name, int new_height) override + { + return set_size<tui_layout_split::set_height_policy> (name, new_height); + } + + tui_adjust_result set_width (const char *name, int new_width) override + { + return set_size<tui_layout_split::set_width_policy> (name, new_width); + } bool top_boxed_p () const override; @@ -217,6 +234,87 @@ class tui_layout_split : public tui_layout_base private: + /* Used to implement set_height and set_width member functions. Set + either the height or width of the window named NAME to NEW_SIZE, + updating the sizes of the other windows around it as needed. The + POLICY is used to specialize this function to adjust either the height + or the width. */ + + template <class Policy> + tui_adjust_result set_size (const char *name, int new_size); + + /* A policy class for use with the set_size member function, use when we + want to adjust the height of a named window. */ + + struct set_height_policy + { + /* Set the height of window named NAME to NEW_HEIGHT in LAYOUT. */ + static tui_adjust_result + set_size (std::unique_ptr<tui_layout_base> &layout, + const char *name, + int new_height) + { + return layout->set_height (name, new_height); + } + + /* Can we adjust the heights of windows in SPLIT? */ + static bool + can_adjust (const tui_layout_split *split) + { + return split->m_vertical; + } + + /* What is the current height of LAYOUT. */ + static int + current_size (std::unique_ptr<tui_layout_base> &layout) + { + return layout->height; + } + + /* Warn about invalid height specification. */ + static void + invalid_size_warning () + { + warning (_("Invalid window height specified")); + } + }; + + /* A policy class for use with the set_size member function, use when we + want to adjust the width of a named window. */ + + struct set_width_policy + { + /* Set the width of window named NAME to NEW_HEIGHT in LAYOUT. */ + static tui_adjust_result + set_size (std::unique_ptr<tui_layout_base> &layout, + const char *name, + int new_width) + { + return layout->set_width (name, new_width); + } + + /* Can we adjust the widths of windows in SPLIT? */ + static bool + can_adjust (const tui_layout_split *split) + { + return !split->m_vertical; + } + + /* What is the current width of LAYOUT. */ + static int + current_size (std::unique_ptr<tui_layout_base> &layout) + { + return layout->width; + } + + /* Warn about invalid height specification. */ + static void + invalid_size_warning () + { + warning (_("Invalid window width specified")); + } + }; + /* Set the weights from the current heights (when m_vertical is true) or widths (when m_vertical is false). */ void set_weights_from_sizes (); @@ -266,6 +364,10 @@ extern void tui_apply_current_layout (); extern void tui_adjust_window_height (struct tui_win_info *win, int new_height); +/* Adjust the window width of WIN to NEW_WIDTH. */ +extern void tui_adjust_window_width (struct tui_win_info *win, + int new_width); + /* The type of a function that is used to create a TUI window. */ typedef std::function<tui_win_info * (const char *name)> window_factory; diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index ba6aca3d078..953af640c93 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -842,10 +842,21 @@ tui_set_tab_width_command (const char *arg, int from_tty) } } +/* Helper function for the user commands to adjust a window's width or + height. The ARG string contains the command line arguments from the + user, which should give the name of a window, and how to adjust the + size. -/* Set the height of the specified window. */ + The Policy type is used to specialise this function for updating either + the width or height of the window. + + On invalid input, or if the size can't be adjusted as requested, then an + error is thrown, otherwise, the window sizes are adjusted, and the + windows redrawn. */ + +template<typename Policy> static void -tui_set_win_height_command (const char *arg, int from_tty) +tui_set_win_size (const char *arg) { /* Make sure the curses mode is enabled. */ tui_enable (); @@ -854,7 +865,7 @@ tui_set_win_height_command (const char *arg, int from_tty) const char *buf = arg; const char *buf_ptr = buf; - int new_height; + int new_size; struct tui_win_info *win_info; buf_ptr = skip_to_space (buf_ptr); @@ -890,18 +901,82 @@ tui_set_win_height_command (const char *arg, int from_tty) if (negate) input_no *= (-1); if (fixed_size) - new_height = input_no; + new_size = input_no; else - new_height = win_info->height + input_no; + new_size = Policy::existing_window_size (win_info) + input_no; /* Now change the window's height, and adjust all other windows around it. */ - tui_adjust_window_height (win_info, new_height); + Policy::adjust_window_size (win_info, new_size); tui_update_gdb_sizes (); } else - error (_("Invalid window height specified")); + Policy::invalid_size_error (); + } +} + +/* Implement the 'tui window height' command (alias 'winheight'). */ + +static void +tui_set_win_height_command (const char *arg, int from_tty) +{ + /* Policy class for use with tui_set_win_size, this policy adjusts the + height of a window. */ + struct height_adjustment_policy + { + /* Called when the size specified is invalid. */ + static void invalid_size_error () + { + error (_("Invalid window height specified")); + } + + /* Return the existing size, height in this case, of a window WIN_INFO. */ + static int existing_window_size (struct tui_win_info *win_info) + { + return win_info->height; + } + + /* Set the size, height in this case, of WIN_INFO to NEW_SIZE. */ + static void adjust_window_size (struct tui_win_info *win_info, + int new_size) + { + tui_adjust_window_height (win_info, new_size); + } + }; + + tui_set_win_size<height_adjustment_policy> (arg); +} + +/* Implement the 'tui window width' command (alias 'winwidth'). */ + +static void +tui_set_win_width_command (const char *arg, int from_tty) +{ + /* Policy class for use with tui_set_win_size, this policy adjusts the + width of a window. */ + struct width_adjustment_policy + { + /* Called when the size specified is invalid. */ + static void invalid_size_error () + { + error (_("Invalid window width specified")); } + + /* Return the existing size, width in this case, of a window WIN_INFO. */ + static int existing_window_size (struct tui_win_info *win_info) + { + return win_info->width; + } + + /* Set the size, width in this case, of WIN_INFO to NEW_SIZE. */ + static void adjust_window_size (struct tui_win_info *win_info, + int new_size) + { + tui_adjust_window_width (win_info, new_size); + } + }; + + tui_set_win_size<width_adjustment_policy> (arg); } /* See tui-data.h. */ @@ -1033,6 +1108,16 @@ Use \"info win\" to see the names of the windows currently being displayed."), add_com_alias ("winheight", winheight_cmd, class_tui, 0); add_com_alias ("wh", winheight_cmd, class_tui, 0); set_cmd_completer (winheight_cmd, winheight_completer); + + cmd_list_element *winwidth_cmd + = add_cmd ("width", class_tui, tui_set_win_width_command, _("\ +Set or modify the width of a specified window.\n\ +Usage: tui window width WINDOW-NAME [+ | -] NUM-LINES\n\ +Use \"info win\" to see the names of the windows currently being displayed."), + &tui_window_cmds); + add_com_alias ("winwidth", winwidth_cmd, class_tui, 0); + set_cmd_completer (winwidth_cmd, winheight_completer); + add_info ("win", tui_all_windows_info, _("List of all displayed windows.\n\ Usage: info win")); -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias 2022-01-28 15:55 ` [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess @ 2022-01-28 17:05 ` Eli Zaretskii 0 siblings, 0 replies; 74+ messages in thread From: Eli Zaretskii @ 2022-01-28 17:05 UTC (permalink / raw) To: Andrew Burgess; +Cc: gdb-patches > Date: Fri, 28 Jan 2022 15:55:08 +0000 > From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> > Cc: Andrew Burgess <aburgess@redhat.com> > > gdb/NEWS | 6 ++ > gdb/doc/gdb.texinfo | 12 ++++ > gdb/testsuite/gdb.tui/winwidth.exp | 62 +++++++++++++++++ > gdb/tui/tui-layout.c | 23 +++++-- > gdb/tui/tui-layout.h | 104 ++++++++++++++++++++++++++++- > gdb/tui/tui-win.c | 99 +++++++++++++++++++++++++-- > 6 files changed, 291 insertions(+), 15 deletions(-) > create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp The documentation parts are OK, thanks. ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes 2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess ` (6 preceding siblings ...) 2022-01-28 15:55 ` [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 01/15] gdb: move some commands into the tui namespace Andrew Burgess ` (16 more replies) 2022-03-04 17:23 ` [PATCH 0/7] TUI command changes, including new winwidth command Tom Tromey 8 siblings, 17 replies; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess I pushed the first two patches from the v1 series, but the rest of that original series does need reviewing - those paches are included in v2 as patches 1 to 5. The remaining 10 patches in the v2 series mostly relate to changing how window resizing, and window layout occurs. The docs content in patches 1 and 5 of the v2 series is unchanged from v1, and was already reviewed, so no new docs review is required there. There is some new docs content in patch 6, but its pretty minor; a docs review is always welcome though. I'm hoping most of the changes in this series will be pretty non-controversial, the only patch which I think might be more of a personal taste issue is the very last one (left last for that reason). I'd suggest selecting the split layout, and then playing with window resizing to get a feel for the new behaviour. Feedback welcome. Thanks, Andrew --- Andrew Burgess (15): gdb: move some commands into the tui namespace gdb/tui: rename tui_layout_base::adjust_size to ::set_height gdb/tui: rename tui_layout_split:set_weights_from_heights gdb/testing/tui: add new functionality to tuiterm.exp gdb/tui: add new 'tui window width' command and 'winwidth' alias gdb/tui: add a tui debugging flag gdb/tui: add left_boxed_p and right_boxed_p member functions gdb/tui/testsuite: refactor new-layout.exp test gdb/tui: avoid fp exception when applying layouts gdb/tui: fairer distribution of excess space during apply gdb/tui: allow cmd window to change size in tui_layout_split::apply gdb/tui: support placing the cmd window into a horizontal layout gdb/testsuite: some additional tests in gdb.tui/scroll.exp gdb/tui: relax restrictions on window max height and width gdb/tui: fair split of delta after a resize gdb/NEWS | 25 ++ gdb/doc/gdb.texinfo | 41 ++- gdb/testsuite/gdb.tui/basic.exp | 4 +- gdb/testsuite/gdb.tui/empty.exp | 14 +- gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++-- gdb/testsuite/gdb.tui/regs.exp | 4 +- gdb/testsuite/gdb.tui/scroll.exp | 4 + gdb/testsuite/gdb.tui/winheight.exp | 77 +++++ gdb/testsuite/gdb.tui/winwidth.exp | 63 ++++ gdb/testsuite/lib/tuiterm.exp | 82 +++++- gdb/tui/tui-command.c | 6 - gdb/tui/tui-command.h | 2 - gdb/tui/tui-layout.c | 419 +++++++++++++++++++++++---- gdb/tui/tui-layout.h | 201 ++++++++++++- gdb/tui/tui-win.c | 149 ++++++++-- gdb/tui/tui.c | 26 ++ gdb/tui/tui.h | 14 + 17 files changed, 1089 insertions(+), 142 deletions(-) create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 01/15] gdb: move some commands into the tui namespace 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-02-06 15:50 ` Eli Zaretskii 2022-02-06 14:12 ` [PATCHv2 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess ` (15 subsequent siblings) 16 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess There are a lot of tui related commands that live in the top-level command name space, e.g. layout, focus, refresh, winheight. Having them at the top level means less typing for the user, which is good, but, I think, makes command discovery harder. In this commit, I propose moving all of the above mentioned commands into the tui namespace, so 'layout' becomes 'tui layout', etc. But I will then add aliases so that the old commands will still work, e.g. I'll make 'layout' an alias for 'tui layout'. The benefit I see in this work is that tui related commands can be more easily discovered by typing 'tui ' and then tab-completing. Also the "official" command is now a tui-sub-command, this is visible in, for example, the help output, e.g.: (gdb) help layout tui layout, layout Change the layout of windows. Usage: tui layout prev | next | LAYOUT-NAME List of tui layout subcommands: tui layout asm -- Apply the "asm" layout. tui layout next -- Apply the next TUI layout. tui layout prev -- Apply the previous TUI layout. tui layout regs -- Apply the TUI register layout. tui layout split -- Apply the "split" layout. tui layout src -- Apply the "src" layout. Which I think is a good thing, it makes it clearer that this is a tui command. I've added a NEWS entry and updated the docs to mention the new and old command names, with the new name being mentioned first. --- gdb/NEWS | 15 +++++++++++++++ gdb/doc/gdb.texinfo | 18 +++++++++++++----- gdb/tui/tui-layout.c | 16 +++++++++++++--- gdb/tui/tui-win.c | 40 ++++++++++++++++++++++++++++++++-------- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 8da68c88def..f97f643b6ee 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -81,6 +81,14 @@ maint show gnu-source-highlight enabled styling to a particular source file, then the Python Pygments library will be used instead. +tui layout +tui focus +tui refresh +tui window height + These are the new names for the old 'layout', 'focus', 'refresh', + and 'winheight' tui commands respectively. The old names still + exist as aliases to these new commands. + * Changed commands maint packet @@ -106,6 +114,13 @@ info win This command now includes information about the width of the tui windows in its output. +layout +focus +refresh +winheight + These commands are now aliases for the 'tui layout', 'tui focus', + 'tui refresh', and 'tui window height' commands respectively. + * Python API ** New function gdb.add_history(), which takes a gdb.Value object diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 2073d929099..4d91741bcbd 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -28866,8 +28866,10 @@ width of the terminal. Because they have weight 2, the source and assembly windows will be twice the height of the command window. -@item layout @var{name} +@kindex tui layout @kindex layout +@item tui layout @var{name} +@itemx layout @var{name} Changes which TUI windows are displayed. The @var{name} parameter controls which layout is shown. It can be either one of the built-in layout names, or the name of a layout defined by the user using @@ -28897,8 +28899,9 @@ register, assembler, and command windows. @end table -@item focus @var{name} @kindex focus +@item tui focus @var{name} +@itemx focus @var{name} Changes which TUI window is currently active for scrolling. The @var{name} parameter can be any of the following: @@ -28922,8 +28925,10 @@ Make the command window active for scrolling. @end table -@item refresh +@kindex tui refresh @kindex refresh +@item tui refresh +@itemx refresh Refresh the screen. This is similar to typing @kbd{C-L}. @item tui reg @var{group} @@ -28959,9 +28964,12 @@ @kindex update Update the source window and the current execution point. -@item winheight @var{name} +@var{count} -@itemx winheight @var{name} -@var{count} +@kindex tui window height @kindex winheight +@item tui window height @var{name} +@var{count} +@itemx tui window height @var{name} -@var{count} +@itemx winheight @var{name} +@var{count} +@itemx winheight @var{name} -@var{count} Change the height of the window @var{name} by @var{count} lines. Positive counts increase the height, while negative counts decrease it. The @var{name} parameter can be the name of any currently visible diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index cef9190c3e1..f8388e3fca5 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -839,6 +839,14 @@ destroy_layout (struct cmd_list_element *self, void *context) static struct cmd_list_element *layout_list; +/* Called to implement 'tui layout'. */ + +static void +tui_layout_command (const char *args, int from_tty) +{ + help_list (layout_list, "tui layout ", all_commands, gdb_stdout); +} + /* Add a "layout" command with name NAME that switches to LAYOUT. */ static struct cmd_list_element * @@ -1017,10 +1025,12 @@ void _initialize_tui_layout (); void _initialize_tui_layout () { - add_basic_prefix_cmd ("layout", class_tui, _("\ + struct cmd_list_element *layout_cmd + = add_prefix_cmd ("layout", class_tui, tui_layout_command, _("\ Change the layout of windows.\n\ -Usage: layout prev | next | LAYOUT-NAME"), - &layout_list, 0, &cmdlist); +Usage: tui layout prev | next | LAYOUT-NAME"), + &layout_list, 0, tui_get_cmd_list ()); + add_com_alias ("layout", layout_cmd, class_tui, 0); add_cmd ("next", class_tui, tui_next_layout_command, _("Apply the next TUI layout."), diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index fd6ca59a728..ba6aca3d078 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -977,6 +977,18 @@ parse_scrolling_args (const char *arg, } } +/* The list of 'tui window' sub-commands. */ + +static cmd_list_element *tui_window_cmds = nullptr; + +/* Called to implement 'tui window'. */ + +static void +tui_window_command (const char *args, int from_tty) +{ + help_list (tui_window_cmds, "tui window ", all_commands, gdb_stdout); +} + /* Function to initialize gdb commands, for tui window manipulation. */ @@ -995,8 +1007,11 @@ _initialize_tui_win () &tui_setlist, &tui_showlist, &setlist, &showlist); - add_com ("refresh", class_tui, tui_refresh_all_command, - _("Refresh the terminal display.")); + cmd_list_element *refresh_cmd + = add_cmd ("refresh", class_tui, tui_refresh_all_command, + _("Refresh the terminal display."), + tui_get_cmd_list ()); + add_com_alias ("refresh", refresh_cmd, class_tui, 0); cmd_list_element *tabset_cmd = add_com ("tabset", class_tui, tui_set_tab_width_command, _("\ @@ -1004,21 +1019,30 @@ Set the width (in characters) of tab stops.\n\ Usage: tabset N")); deprecate_cmd (tabset_cmd, "set tui tab-width"); + /* Setup the 'tui window' list of command. */ + add_prefix_cmd ("window", class_tui, tui_window_command, + _("Text User Interface window commands."), + &tui_window_cmds, 1, tui_get_cmd_list ()); + cmd_list_element *winheight_cmd - = add_com ("winheight", class_tui, tui_set_win_height_command, _("\ + = add_cmd ("height", class_tui, tui_set_win_height_command, _("\ Set or modify the height of a specified window.\n\ -Usage: winheight WINDOW-NAME [+ | -] NUM-LINES\n\ -Use \"info win\" to see the names of the windows currently being displayed.")); +Usage: tui window height WINDOW-NAME [+ | -] NUM-LINES\n\ +Use \"info win\" to see the names of the windows currently being displayed."), + &tui_window_cmds); + add_com_alias ("winheight", winheight_cmd, class_tui, 0); add_com_alias ("wh", winheight_cmd, class_tui, 0); set_cmd_completer (winheight_cmd, winheight_completer); add_info ("win", tui_all_windows_info, _("List of all displayed windows.\n\ Usage: info win")); cmd_list_element *focus_cmd - = add_com ("focus", class_tui, tui_set_focus_command, _("\ + = add_cmd ("focus", class_tui, tui_set_focus_command, _("\ Set focus to named window or next/prev window.\n\ -Usage: focus [WINDOW-NAME | next | prev]\n\ -Use \"info win\" to see the names of the windows currently being displayed.")); +Usage: tui focus [WINDOW-NAME | next | prev]\n\ +Use \"info win\" to see the names of the windows currently being displayed."), + tui_get_cmd_list ()); + add_com_alias ("focus", focus_cmd, class_tui, 0); add_com_alias ("fs", focus_cmd, class_tui, 0); set_cmd_completer (focus_cmd, focus_completer); add_com ("+", class_tui, tui_scroll_forward_command, _("\ -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 01/15] gdb: move some commands into the tui namespace 2022-02-06 14:12 ` [PATCHv2 01/15] gdb: move some commands into the tui namespace Andrew Burgess @ 2022-02-06 15:50 ` Eli Zaretskii 0 siblings, 0 replies; 74+ messages in thread From: Eli Zaretskii @ 2022-02-06 15:50 UTC (permalink / raw) To: Andrew Burgess; +Cc: gdb-patches > Date: Sun, 6 Feb 2022 14:12:39 +0000 > From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> > Cc: Andrew Burgess <aburgess@redhat.com> > > gdb/NEWS | 15 +++++++++++++++ > gdb/doc/gdb.texinfo | 18 +++++++++++++----- > gdb/tui/tui-layout.c | 16 +++++++++++++--- > gdb/tui/tui-win.c | 40 ++++++++++++++++++++++++++++++++-------- > 4 files changed, 73 insertions(+), 16 deletions(-) OK for the documentation parts. It is up to you whether to advertise the old commands (which are now aliases) in the manual. We could remove them from there. ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 01/15] gdb: move some commands into the tui namespace Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess ` (14 subsequent siblings) 16 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess Rename tui_layout_base::adjust_size to tui_layout_base::set_height, the new name more accurately reflects what this member function does, and makes it easier for a later commit to add a new tui_layout_base::set_width member function. There should be no user visible changes after this commit. --- gdb/tui/tui-layout.c | 6 +++--- gdb/tui/tui-layout.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index f8388e3fca5..4c355c79d65 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -118,7 +118,7 @@ tui_apply_current_layout () void tui_adjust_window_height (struct tui_win_info *win, int new_height) { - applied_layout->adjust_size (win->name (), new_height); + applied_layout->set_height (win->name (), new_height); } /* Set the current layout to LAYOUT. */ @@ -570,7 +570,7 @@ tui_layout_split::set_weights_from_heights () /* See tui-layout.h. */ tui_adjust_result -tui_layout_split::adjust_size (const char *name, int new_height) +tui_layout_split::set_height (const char *name, int new_height) { /* Look through the children. If one is a layout holding the named window, we're done; or if one actually is the named window, @@ -579,7 +579,7 @@ tui_layout_split::adjust_size (const char *name, int new_height) for (int i = 0; i < m_splits.size (); ++i) { tui_adjust_result adjusted - = m_splits[i].layout->adjust_size (name, new_height); + = m_splits[i].layout->set_height (name, new_height); if (adjusted == HANDLED) return HANDLED; if (adjusted == FOUND) diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index b9a5d9b898d..acea7ac8f64 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -75,9 +75,9 @@ class tui_layout_base return nullptr; } - /* Adjust the size of the window named NAME to NEW_HEIGHT, updating + /* Set the height of the window named NAME to NEW_HEIGHT, updating the sizes of the other windows around it. */ - virtual tui_adjust_result adjust_size (const char *name, int new_height) = 0; + virtual tui_adjust_result set_height (const char *name, int new_height) = 0; /* Remove some windows from the layout, leaving the command window and the window being passed in here. */ @@ -127,7 +127,7 @@ class tui_layout_window : public tui_layout_base return m_contents.c_str (); } - tui_adjust_result adjust_size (const char *name, int new_height) override + tui_adjust_result set_height (const char *name, int new_height) override { return m_contents == name ? FOUND : NOT_FOUND; } @@ -192,7 +192,7 @@ class tui_layout_split : public tui_layout_base void apply (int x, int y, int width, int height) override; - tui_adjust_result adjust_size (const char *name, int new_height) override; + tui_adjust_result set_height (const char *name, int new_height) override; bool top_boxed_p () const override; -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 01/15] gdb: move some commands into the tui namespace Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess ` (13 subsequent siblings) 16 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess In a following commit I'm going to add the ability to change the width of a tui window (when in a horizontal layout). As a result, some of the places where we currently hard-code references to height need to be changed to handle either height, or width, based on whether we are in a vertical, or horizontal layout. This commit renames set_weights_from_heights to set_weights_from_sizes, and makes the function use either the height, or width as appropriate. Currently, the only place that we call this function is from the tui_layout_split::set_height function, in a part of the code we will only reach for vertical layouts, so the new code is not actually being used, but, this small change will help make later patches smaller, so I'm proposing this as a stand alone change. There should be no user visible changes after this commit. --- gdb/tui/tui-layout.c | 9 +++++---- gdb/tui/tui-layout.h | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 4c355c79d65..9e856ccf3fa 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -561,10 +561,11 @@ tui_layout_split::bottom_boxed_p () const /* See tui-layout.h. */ void -tui_layout_split::set_weights_from_heights () +tui_layout_split::set_weights_from_sizes () { for (int i = 0; i < m_splits.size (); ++i) - m_splits[i].weight = m_splits[i].layout->height; + m_splits[i].weight + = m_vertical ? m_splits[i].layout->height : m_splits[i].layout->width; } /* See tui-layout.h. */ @@ -596,7 +597,7 @@ tui_layout_split::set_height (const char *name, int new_height) if (m_splits[found_index].layout->height == new_height) return HANDLED; - set_weights_from_heights (); + set_weights_from_sizes (); int delta = m_splits[found_index].weight - new_height; m_splits[found_index].weight = new_height; @@ -634,7 +635,7 @@ tui_layout_split::set_height (const char *name, int new_height) { warning (_("Invalid window height specified")); /* Effectively undo any modifications made here. */ - set_weights_from_heights (); + set_weights_from_sizes (); } else { diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index acea7ac8f64..8f41835b94c 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -217,8 +217,9 @@ class tui_layout_split : public tui_layout_base private: - /* Set the weights from the current heights. */ - void set_weights_from_heights (); + /* Set the weights from the current heights (when m_vertical is true) or + widths (when m_vertical is false). */ + void set_weights_from_sizes (); struct split { -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (2 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-03-04 16:29 ` Tom Tromey 2022-02-06 14:12 ` [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess ` (12 subsequent siblings) 16 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess While working on later patches in this series, I was running into csi control codes being emitted from ncurses that are not currently handled by out gdb/testsuite/lib/tuiterm.exp. This commit adds support for these additional control sequences. The new sequences are 'Insert Line', 'Delete Characters', and 'Scroll Down'. There are no new tests in this commit, but I was running into these sequences while developing later patches in this series. However, which control sequences ncurses emits can vary wildly depending on the screen contents. It is possible that I only hit some of these sequences while debugging the later patches (i.e. printing extra content to the terminal), some of these might no longer be needed given the tests as now written. Still, I think it is worth merging these to improve tuiterm.exp. Additionally, I noticed a bug in 'Erase in Line' that this commit fixes; in mode 1 the erase should be from the start of the line through to the cursor, not to the character before the cursor. This bug would mean that random characters would sometimes be left in the terminal output. --- gdb/testsuite/lib/tuiterm.exp | 82 ++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp index 38948015e96..06d2e091ca5 100644 --- a/gdb/testsuite/lib/tuiterm.exp +++ b/gdb/testsuite/lib/tuiterm.exp @@ -317,13 +317,40 @@ namespace eval Term { # From cursor to end. _clear_in_line $_cur_col $_cols $_cur_row } elseif {$arg == 1} { - _clear_in_line 0 $_cur_col $_cur_row + _clear_in_line 0 [expr $_cur_col + 1] $_cur_row } elseif {$arg == 2} { _clear_in_line 0 $_cols $_cur_row } } } + # Insert Line + # + # https://vt100.net/docs/vt510-rm/IL.html + proc _csi_L {args} { + set arg [_default [lindex $args 0] 1] + + _log_cur "Insert Line ($arg)" { + variable _cur_col + variable _cur_row + variable _rows + variable _cols + variable _chars + + set y [expr $_rows - 2] + set next_y [expr $y + 1] + while {$y >= $_cur_row} { + for {set x 0} {$x < $_cols} {incr x} { + set _chars($x,$next_y) $_chars($x,$y) + } + incr y -1 + incr next_y -1 + } + + _clear_lines $_cur_row $_rows + } + } + # Delete line. # # https://vt100.net/docs/vt510-rm/DL.html @@ -349,6 +376,59 @@ namespace eval Term { } } + # Delete Characters + # + # https://vt100.net/docs/vt510-rm/DCH.html + proc _csi_P {args} { + set count [_default [lindex $args 0] 1] + + _log_cur "Delete Character ($count)" { + variable _cur_col + variable _cur_row + variable _cols + variable _chars + + set dx [expr $_cur_col + 1] + set sx [expr $_cur_col + 1 + $count] + set y $_cur_row + + while {$sx < $_cols} { + set _chars($dx,$y) $_chars($sx,$y) + incr sx + incr dx + } + _clear_in_line $dx $sx $y + } + } + + # Pan Down + # + # https://vt100.net/docs/vt510-rm/SU.html + proc _csi_S {args} { + set count [_default [lindex $args 0] 1] + + _log_cur "Pan Down ($count)" { + variable _cur_col + variable _cur_row + variable _cols + variable _rows + variable _chars + + set dy 0 + set y $count + + while {$y < $_rows} { + for {set x 0} {$x < $_cols} {incr x} { + set _chars($x,$dy) $_chars($x,$y) + } + incr y 1 + incr dy 1 + } + + _clear_lines $dy $_rows + } + } + # Erase chars. # # https://vt100.net/docs/vt510-rm/ECH.html -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp 2022-02-06 14:12 ` [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess @ 2022-03-04 16:29 ` Tom Tromey 0 siblings, 0 replies; 74+ messages in thread From: Tom Tromey @ 2022-03-04 16:29 UTC (permalink / raw) To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess >>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes: Andrew> There are no new tests in this commit, but I was running into these Andrew> sequences while developing later patches in this series. However, Andrew> which control sequences ncurses emits can vary wildly depending on the Andrew> screen contents. It is possible that I only hit some of these Andrew> sequences while debugging the later patches (i.e. printing extra Andrew> content to the terminal), some of these might no longer be needed Andrew> given the tests as now written. Andrew> Still, I think it is worth merging these to improve tuiterm.exp. Agreed, and just to be clear, the history of tuiterm.exp is that I implemented more or less the minimum needed based on the tests I had written. I wouldn't be surprised if future tests find other holes. Tom ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (3 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-02-06 15:52 ` Eli Zaretskii 2022-03-03 18:52 ` Pedro Alves 2022-02-06 14:12 ` [PATCHv2 06/15] gdb/tui: add a tui debugging flag Andrew Burgess ` (11 subsequent siblings) 16 siblings, 2 replies; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit adds a new command 'tui window width', and an alias 'winwidth'. This command is equivalent to the old 'winheight' command (which was recently renamed 'tui window height'). Even though I recently moved the old tui commands under the tui namespace, and I would strongly encourage all new tui commands to be added as 'tui ....' only (users can create their own top-level aliases if they want), I'm breaking that suggestion here, and adding a 'winwidth' alias. Given that we already have 'winheight' and have done for years, it just didn't seem right to no have the matching 'winwidth'. You might notice in the test that the window resizing doesn't quite work right. I setup a horizontal layout, then grow and shrink the windows. At the end of the test the windows should be back to their original size... ... they are not. This isn't my fault, honest! GDB's window resizing is a little ... temperamental, and is prone to getting things slightly wrong during resizes, off by 1 type things. This is true for height resizing, as well as the new width resizing. I'm currently working on a patch to improve the resizing algorithm, which should improve things in this area. For now, I'm happy that the width resizing is as good as the height resizing, given the existing quirks. As for the changes in gdb itself, I've mostly just templated the existing height adjustment code so that the two functions tui_layout_split::adjust_size (tui-layout.c) and tui_set_win_height_command (tui-win.c) now have a template parameter "policy", this policy allows me to specialise the functions for either width or height adjustment. Function arguments, and locals, are renamed, replacing 'height' with 'size'. --- gdb/NEWS | 6 ++ gdb/doc/gdb.texinfo | 12 ++++ gdb/testsuite/gdb.tui/winwidth.exp | 62 +++++++++++++++++ gdb/tui/tui-layout.c | 23 +++++-- gdb/tui/tui-layout.h | 104 ++++++++++++++++++++++++++++- gdb/tui/tui-win.c | 99 +++++++++++++++++++++++++-- 6 files changed, 291 insertions(+), 15 deletions(-) create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp diff --git a/gdb/NEWS b/gdb/NEWS index f97f643b6ee..1faef78056a 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -89,6 +89,12 @@ tui window height and 'winheight' tui commands respectively. The old names still exist as aliases to these new commands. +tui window width +winwidth + The new command 'tui window width', and the alias 'winwidth' allow + the width of a tui window to be adjusted when windows are laid out + in horizontal mode. + * Changed commands maint packet diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 4d91741bcbd..4793a054f7e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -28975,6 +28975,18 @@ it. The @var{name} parameter can be the name of any currently visible window. The names of the currently visible windows can be discovered using @kbd{info win} (@pxref{info_win_command,,info win}). + +@kindex tui window width +@kindex winwidth +@item tui window width @var{name} +@var{count} +@itemx tui window width @var{name} -@var{count} +@itemx winwidth @var{name} +@var{count} +@itemx winwidth @var{name} -@var{count} +Change the width of the window @var{name} by @var{count} columns. +Positive counts increase the width, while negative counts decrease it. +The @var{name} parameter can be the name of any currently visible +window. The names of the currently visible windows can be discovered +using @code{info win} (@pxref{info_win_command,,info win}). @end table @node TUI Configuration diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp new file mode 100644 index 00000000000..b0a838b578f --- /dev/null +++ b/gdb/testsuite/gdb.tui/winwidth.exp @@ -0,0 +1,62 @@ +# Copyright 2022 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test the "winwidth" command. + +tuiterm_env + +standard_testfile tui-layout.c + +if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} { + return -1 +} + +Term::clean_restart 24 80 $testfile +if {![Term::enter_tui]} { + unsupported "TUI not supported" + return +} + +Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1" +Term::command "layout h" + +with_test_prefix "original window sizes" { + Term::check_box "source box" 0 0 40 15 + Term::check_box "asm box" 39 0 41 15 + Term::command "winwidth src +5" +} + +with_test_prefix "after src +5" { + Term::check_box "source box" 0 0 44 15 + Term::check_box "asm box" 43 0 37 15 + Term::command "winwidth asm -5" +} + +with_test_prefix "after asm -5" { + Term::check_box "source box" 0 0 48 15 + Term::check_box "asm box" 47 0 33 15 + Term::command "winwidth asm +8" +} + +with_test_prefix "after asm +8" { + Term::check_box "source box" 0 0 39 15 + Term::check_box "asm box" 38 0 42 15 + Term::command "winwidth src -2" +} + +with_test_prefix "after src -2" { + Term::check_box "source box" 0 0 36 15 + Term::check_box "asm box" 35 0 45 15 +} diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 9e856ccf3fa..13e4d462426 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -121,6 +121,14 @@ tui_adjust_window_height (struct tui_win_info *win, int new_height) applied_layout->set_height (win->name (), new_height); } +/* See tui-layout. */ + +void +tui_adjust_window_width (struct tui_win_info *win, int new_width) +{ + applied_layout->set_width (win->name (), new_width); +} + /* Set the current layout to LAYOUT. */ static void @@ -570,8 +578,9 @@ tui_layout_split::set_weights_from_sizes () /* See tui-layout.h. */ +template<class Policy> tui_adjust_result -tui_layout_split::set_height (const char *name, int new_height) +tui_layout_split::set_size (const char *name, int new_size) { /* Look through the children. If one is a layout holding the named window, we're done; or if one actually is the named window, @@ -580,12 +589,12 @@ tui_layout_split::set_height (const char *name, int new_height) for (int i = 0; i < m_splits.size (); ++i) { tui_adjust_result adjusted - = m_splits[i].layout->set_height (name, new_height); + = Policy::set_size (m_splits[i].layout, name, new_size); if (adjusted == HANDLED) return HANDLED; if (adjusted == FOUND) { - if (!m_vertical) + if (!Policy::can_adjust (this)) return FOUND; found_index = i; break; @@ -594,12 +603,12 @@ tui_layout_split::set_height (const char *name, int new_height) if (found_index == -1) return NOT_FOUND; - if (m_splits[found_index].layout->height == new_height) + if (Policy::current_size (m_splits[found_index].layout) == new_size) return HANDLED; set_weights_from_sizes (); - int delta = m_splits[found_index].weight - new_height; - m_splits[found_index].weight = new_height; + int delta = m_splits[found_index].weight - new_size; + m_splits[found_index].weight = new_size; /* Distribute the "delta" over the next window; but if the next window cannot hold it all, keep going until we either find a @@ -633,7 +642,7 @@ tui_layout_split::set_height (const char *name, int new_height) if (delta != 0) { - warning (_("Invalid window height specified")); + Policy::invalid_size_warning (); /* Effectively undo any modifications made here. */ set_weights_from_sizes (); } diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index 8f41835b94c..f4ef0895f1f 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -79,6 +79,10 @@ class tui_layout_base the sizes of the other windows around it. */ virtual tui_adjust_result set_height (const char *name, int new_height) = 0; + /* Set the width of the window named NAME to NEW_WIDTH, updating + the sizes of the other windows around it. */ + virtual tui_adjust_result set_width (const char *name, int new_width) = 0; + /* Remove some windows from the layout, leaving the command window and the window being passed in here. */ virtual void remove_windows (const char *name) = 0; @@ -132,6 +136,11 @@ class tui_layout_window : public tui_layout_base return m_contents == name ? FOUND : NOT_FOUND; } + tui_adjust_result set_width (const char *name, int new_width) override + { + return m_contents == name ? FOUND : NOT_FOUND; + } + bool top_boxed_p () const override; bool bottom_boxed_p () const override; @@ -192,7 +201,15 @@ class tui_layout_split : public tui_layout_base void apply (int x, int y, int width, int height) override; - tui_adjust_result set_height (const char *name, int new_height) override; + tui_adjust_result set_height (const char *name, int new_height) override + { + return set_size<tui_layout_split::set_height_policy> (name, new_height); + } + + tui_adjust_result set_width (const char *name, int new_width) override + { + return set_size<tui_layout_split::set_width_policy> (name, new_width); + } bool top_boxed_p () const override; @@ -217,6 +234,87 @@ class tui_layout_split : public tui_layout_base private: + /* Used to implement set_height and set_width member functions. Set + either the height or width of the window named NAME to NEW_SIZE, + updating the sizes of the other windows around it as needed. The + POLICY is used to specialize this function to adjust either the height + or the width. */ + + template <class Policy> + tui_adjust_result set_size (const char *name, int new_size); + + /* A policy class for use with the set_size member function, use when we + want to adjust the height of a named window. */ + + struct set_height_policy + { + /* Set the height of window named NAME to NEW_HEIGHT in LAYOUT. */ + static tui_adjust_result + set_size (std::unique_ptr<tui_layout_base> &layout, + const char *name, + int new_height) + { + return layout->set_height (name, new_height); + } + + /* Can we adjust the heights of windows in SPLIT? */ + static bool + can_adjust (const tui_layout_split *split) + { + return split->m_vertical; + } + + /* What is the current height of LAYOUT. */ + static int + current_size (std::unique_ptr<tui_layout_base> &layout) + { + return layout->height; + } + + /* Warn about invalid height specification. */ + static void + invalid_size_warning () + { + warning (_("Invalid window height specified")); + } + }; + + /* A policy class for use with the set_size member function, use when we + want to adjust the width of a named window. */ + + struct set_width_policy + { + /* Set the width of window named NAME to NEW_HEIGHT in LAYOUT. */ + static tui_adjust_result + set_size (std::unique_ptr<tui_layout_base> &layout, + const char *name, + int new_width) + { + return layout->set_width (name, new_width); + } + + /* Can we adjust the widths of windows in SPLIT? */ + static bool + can_adjust (const tui_layout_split *split) + { + return !split->m_vertical; + } + + /* What is the current width of LAYOUT. */ + static int + current_size (std::unique_ptr<tui_layout_base> &layout) + { + return layout->width; + } + + /* Warn about invalid height specification. */ + static void + invalid_size_warning () + { + warning (_("Invalid window width specified")); + } + }; + /* Set the weights from the current heights (when m_vertical is true) or widths (when m_vertical is false). */ void set_weights_from_sizes (); @@ -266,6 +364,10 @@ extern void tui_apply_current_layout (); extern void tui_adjust_window_height (struct tui_win_info *win, int new_height); +/* Adjust the window width of WIN to NEW_WIDTH. */ +extern void tui_adjust_window_width (struct tui_win_info *win, + int new_width); + /* The type of a function that is used to create a TUI window. */ typedef std::function<tui_win_info * (const char *name)> window_factory; diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index ba6aca3d078..953af640c93 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -842,10 +842,21 @@ tui_set_tab_width_command (const char *arg, int from_tty) } } +/* Helper function for the user commands to adjust a window's width or + height. The ARG string contains the command line arguments from the + user, which should give the name of a window, and how to adjust the + size. -/* Set the height of the specified window. */ + The Policy type is used to specialise this function for updating either + the width or height of the window. + + On invalid input, or if the size can't be adjusted as requested, then an + error is thrown, otherwise, the window sizes are adjusted, and the + windows redrawn. */ + +template<typename Policy> static void -tui_set_win_height_command (const char *arg, int from_tty) +tui_set_win_size (const char *arg) { /* Make sure the curses mode is enabled. */ tui_enable (); @@ -854,7 +865,7 @@ tui_set_win_height_command (const char *arg, int from_tty) const char *buf = arg; const char *buf_ptr = buf; - int new_height; + int new_size; struct tui_win_info *win_info; buf_ptr = skip_to_space (buf_ptr); @@ -890,18 +901,82 @@ tui_set_win_height_command (const char *arg, int from_tty) if (negate) input_no *= (-1); if (fixed_size) - new_height = input_no; + new_size = input_no; else - new_height = win_info->height + input_no; + new_size = Policy::existing_window_size (win_info) + input_no; /* Now change the window's height, and adjust all other windows around it. */ - tui_adjust_window_height (win_info, new_height); + Policy::adjust_window_size (win_info, new_size); tui_update_gdb_sizes (); } else - error (_("Invalid window height specified")); + Policy::invalid_size_error (); + } +} + +/* Implement the 'tui window height' command (alias 'winheight'). */ + +static void +tui_set_win_height_command (const char *arg, int from_tty) +{ + /* Policy class for use with tui_set_win_size, this policy adjusts the + height of a window. */ + struct height_adjustment_policy + { + /* Called when the size specified is invalid. */ + static void invalid_size_error () + { + error (_("Invalid window height specified")); + } + + /* Return the existing size, height in this case, of a window WIN_INFO. */ + static int existing_window_size (struct tui_win_info *win_info) + { + return win_info->height; + } + + /* Set the size, height in this case, of WIN_INFO to NEW_SIZE. */ + static void adjust_window_size (struct tui_win_info *win_info, + int new_size) + { + tui_adjust_window_height (win_info, new_size); + } + }; + + tui_set_win_size<height_adjustment_policy> (arg); +} + +/* Implement the 'tui window width' command (alias 'winwidth'). */ + +static void +tui_set_win_width_command (const char *arg, int from_tty) +{ + /* Policy class for use with tui_set_win_size, this policy adjusts the + width of a window. */ + struct width_adjustment_policy + { + /* Called when the size specified is invalid. */ + static void invalid_size_error () + { + error (_("Invalid window width specified")); } + + /* Return the existing size, width in this case, of a window WIN_INFO. */ + static int existing_window_size (struct tui_win_info *win_info) + { + return win_info->width; + } + + /* Set the size, width in this case, of WIN_INFO to NEW_SIZE. */ + static void adjust_window_size (struct tui_win_info *win_info, + int new_size) + { + tui_adjust_window_width (win_info, new_size); + } + }; + + tui_set_win_size<width_adjustment_policy> (arg); } /* See tui-data.h. */ @@ -1033,6 +1108,16 @@ Use \"info win\" to see the names of the windows currently being displayed."), add_com_alias ("winheight", winheight_cmd, class_tui, 0); add_com_alias ("wh", winheight_cmd, class_tui, 0); set_cmd_completer (winheight_cmd, winheight_completer); + + cmd_list_element *winwidth_cmd + = add_cmd ("width", class_tui, tui_set_win_width_command, _("\ +Set or modify the width of a specified window.\n\ +Usage: tui window width WINDOW-NAME [+ | -] NUM-LINES\n\ +Use \"info win\" to see the names of the windows currently being displayed."), + &tui_window_cmds); + add_com_alias ("winwidth", winwidth_cmd, class_tui, 0); + set_cmd_completer (winwidth_cmd, winheight_completer); + add_info ("win", tui_all_windows_info, _("List of all displayed windows.\n\ Usage: info win")); -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias 2022-02-06 14:12 ` [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess @ 2022-02-06 15:52 ` Eli Zaretskii 2022-02-09 15:33 ` Andrew Burgess 2022-03-03 18:52 ` Pedro Alves 1 sibling, 1 reply; 74+ messages in thread From: Eli Zaretskii @ 2022-02-06 15:52 UTC (permalink / raw) To: Andrew Burgess; +Cc: gdb-patches > Date: Sun, 6 Feb 2022 14:12:43 +0000 > From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> > Cc: Andrew Burgess <aburgess@redhat.com> > > gdb/NEWS | 6 ++ > gdb/doc/gdb.texinfo | 12 ++++ > gdb/testsuite/gdb.tui/winwidth.exp | 62 +++++++++++++++++ > gdb/tui/tui-layout.c | 23 +++++-- > gdb/tui/tui-layout.h | 104 ++++++++++++++++++++++++++++- > gdb/tui/tui-win.c | 99 +++++++++++++++++++++++++-- > 6 files changed, 291 insertions(+), 15 deletions(-) > create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp OK for the documentation parts. Btw, should we mention that this new command will only have effect if more than one window is displayed? ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias 2022-02-06 15:52 ` Eli Zaretskii @ 2022-02-09 15:33 ` Andrew Burgess 2022-02-09 17:03 ` Eli Zaretskii 0 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-02-09 15:33 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches Eli Zaretskii via Gdb-patches <gdb-patches@sourceware.org> writes: >> Date: Sun, 6 Feb 2022 14:12:43 +0000 >> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> >> Cc: Andrew Burgess <aburgess@redhat.com> >> >> gdb/NEWS | 6 ++ >> gdb/doc/gdb.texinfo | 12 ++++ >> gdb/testsuite/gdb.tui/winwidth.exp | 62 +++++++++++++++++ >> gdb/tui/tui-layout.c | 23 +++++-- >> gdb/tui/tui-layout.h | 104 ++++++++++++++++++++++++++++- >> gdb/tui/tui-win.c | 99 +++++++++++++++++++++++++-- >> 6 files changed, 291 insertions(+), 15 deletions(-) >> create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp > > OK for the documentation parts. > > Btw, should we mention that this new command will only have effect if > more than one window is displayed? What about this for the description of 'tui window width'? The second paragraph is new: @kindex tui window width @kindex winwidth @item tui window width @var{name} +@var{count} @itemx tui window width @var{name} -@var{count} @itemx winwidth @var{name} +@var{count} @itemx winwidth @var{name} -@var{count} Change the width of the window @var{name} by @var{count} columns. Positive counts increase the width, while negative counts decrease it. The @var{name} parameter can be the name of any currently visible window. The names of the currently visible windows can be discovered using @code{info win} (@pxref{info_win_command,,info win}). The set of currently visible windows must always fill the terminal, and so, it is only possible to resize on window if there are other visible windows that can either give or receive the extra terminal space. If this is OK, then I would propose adding the same paragraph to the description of 'tui window height' which obviously has the same restrictions. The complete patch, including the new paragraphs is included below. Thanks, Andrew --- commit 3fd38b7966faa8371f91c70c4e4914b6c786b6ef Author: Andrew Burgess <aburgess@redhat.com> Date: Mon Jan 24 22:02:59 2022 +0000 gdb/tui: add new 'tui window width' command and 'winwidth' alias This commit adds a new command 'tui window width', and an alias 'winwidth'. This command is equivalent to the old 'winheight' command (which was recently renamed 'tui window height'). Even though I recently moved the old tui commands under the tui namespace, and I would strongly encourage all new tui commands to be added as 'tui ....' only (users can create their own top-level aliases if they want), I'm breaking that suggestion here, and adding a 'winwidth' alias. Given that we already have 'winheight' and have done for years, it just didn't seem right to no have the matching 'winwidth'. You might notice in the test that the window resizing doesn't quite work right. I setup a horizontal layout, then grow and shrink the windows. At the end of the test the windows should be back to their original size... ... they are not. This isn't my fault, honest! GDB's window resizing is a little ... temperamental, and is prone to getting things slightly wrong during resizes, off by 1 type things. This is true for height resizing, as well as the new width resizing. Later patches in this series will rework the resizing algorithm, which should improve things in this area. For now, I'm happy that the width resizing is as good as the height resizing, given the existing quirks. For the docs side I include a paragraph that explains how multiple windows are required before the width can be adjusted. For completeness, I've added the same paragraph to the winheight description. With the predefined layouts this extra paragraph is not really needed for winheight, as there are always multiple windows on the screen. However, with custom layouts, this might not be true, so adding the paragraph seems like a good idea. As for the changes in gdb itself, I've mostly just templated the existing height adjustment code so that the two functions tui_layout_split::adjust_size (tui-layout.c) and tui_set_win_height_command (tui-win.c) now have a template parameter "policy", this policy allows me to specialise the functions for either width or height adjustment. Function arguments, and locals, are renamed, replacing 'height' with 'size'. diff --git a/gdb/NEWS b/gdb/NEWS index b06eb473ffb..3a05b95a3d9 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -97,6 +97,12 @@ tui window height and 'winheight' tui commands respectively. The old names still exist as aliases to these new commands. +tui window width +winwidth + The new command 'tui window width', and the alias 'winwidth' allow + the width of a tui window to be adjusted when windows are laid out + in horizontal mode. + * Changed commands maint packet diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6ddcc099cd8..e144255df69 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -29044,6 +29044,28 @@ it. The @var{name} parameter can be the name of any currently visible window. The names of the currently visible windows can be discovered using @kbd{info win} (@pxref{info_win_command,,info win}). + +The set of currently visible windows must always fill the terminal, +and so, it is only possible to resize on window if there are other +visible windows that can either give or receive the extra terminal +space. + +@kindex tui window width +@kindex winwidth +@item tui window width @var{name} +@var{count} +@itemx tui window width @var{name} -@var{count} +@itemx winwidth @var{name} +@var{count} +@itemx winwidth @var{name} -@var{count} +Change the width of the window @var{name} by @var{count} columns. +Positive counts increase the width, while negative counts decrease it. +The @var{name} parameter can be the name of any currently visible +window. The names of the currently visible windows can be discovered +using @code{info win} (@pxref{info_win_command,,info win}). + +The set of currently visible windows must always fill the terminal, +and so, it is only possible to resize on window if there are other +visible windows that can either give or receive the extra terminal +space. @end table @node TUI Configuration diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp new file mode 100644 index 00000000000..b0a838b578f --- /dev/null +++ b/gdb/testsuite/gdb.tui/winwidth.exp @@ -0,0 +1,62 @@ +# Copyright 2022 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test the "winwidth" command. + +tuiterm_env + +standard_testfile tui-layout.c + +if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} { + return -1 +} + +Term::clean_restart 24 80 $testfile +if {![Term::enter_tui]} { + unsupported "TUI not supported" + return +} + +Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1" +Term::command "layout h" + +with_test_prefix "original window sizes" { + Term::check_box "source box" 0 0 40 15 + Term::check_box "asm box" 39 0 41 15 + Term::command "winwidth src +5" +} + +with_test_prefix "after src +5" { + Term::check_box "source box" 0 0 44 15 + Term::check_box "asm box" 43 0 37 15 + Term::command "winwidth asm -5" +} + +with_test_prefix "after asm -5" { + Term::check_box "source box" 0 0 48 15 + Term::check_box "asm box" 47 0 33 15 + Term::command "winwidth asm +8" +} + +with_test_prefix "after asm +8" { + Term::check_box "source box" 0 0 39 15 + Term::check_box "asm box" 38 0 42 15 + Term::command "winwidth src -2" +} + +with_test_prefix "after src -2" { + Term::check_box "source box" 0 0 36 15 + Term::check_box "asm box" 35 0 45 15 +} diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 9e856ccf3fa..13e4d462426 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -121,6 +121,14 @@ tui_adjust_window_height (struct tui_win_info *win, int new_height) applied_layout->set_height (win->name (), new_height); } +/* See tui-layout. */ + +void +tui_adjust_window_width (struct tui_win_info *win, int new_width) +{ + applied_layout->set_width (win->name (), new_width); +} + /* Set the current layout to LAYOUT. */ static void @@ -570,8 +578,9 @@ tui_layout_split::set_weights_from_sizes () /* See tui-layout.h. */ +template<class Policy> tui_adjust_result -tui_layout_split::set_height (const char *name, int new_height) +tui_layout_split::set_size (const char *name, int new_size) { /* Look through the children. If one is a layout holding the named window, we're done; or if one actually is the named window, @@ -580,12 +589,12 @@ tui_layout_split::set_height (const char *name, int new_height) for (int i = 0; i < m_splits.size (); ++i) { tui_adjust_result adjusted - = m_splits[i].layout->set_height (name, new_height); + = Policy::set_size (m_splits[i].layout, name, new_size); if (adjusted == HANDLED) return HANDLED; if (adjusted == FOUND) { - if (!m_vertical) + if (!Policy::can_adjust (this)) return FOUND; found_index = i; break; @@ -594,12 +603,12 @@ tui_layout_split::set_height (const char *name, int new_height) if (found_index == -1) return NOT_FOUND; - if (m_splits[found_index].layout->height == new_height) + if (Policy::current_size (m_splits[found_index].layout) == new_size) return HANDLED; set_weights_from_sizes (); - int delta = m_splits[found_index].weight - new_height; - m_splits[found_index].weight = new_height; + int delta = m_splits[found_index].weight - new_size; + m_splits[found_index].weight = new_size; /* Distribute the "delta" over the next window; but if the next window cannot hold it all, keep going until we either find a @@ -633,7 +642,7 @@ tui_layout_split::set_height (const char *name, int new_height) if (delta != 0) { - warning (_("Invalid window height specified")); + Policy::invalid_size_warning (); /* Effectively undo any modifications made here. */ set_weights_from_sizes (); } diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index 8f41835b94c..f4ef0895f1f 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -79,6 +79,10 @@ class tui_layout_base the sizes of the other windows around it. */ virtual tui_adjust_result set_height (const char *name, int new_height) = 0; + /* Set the width of the window named NAME to NEW_WIDTH, updating + the sizes of the other windows around it. */ + virtual tui_adjust_result set_width (const char *name, int new_width) = 0; + /* Remove some windows from the layout, leaving the command window and the window being passed in here. */ virtual void remove_windows (const char *name) = 0; @@ -132,6 +136,11 @@ class tui_layout_window : public tui_layout_base return m_contents == name ? FOUND : NOT_FOUND; } + tui_adjust_result set_width (const char *name, int new_width) override + { + return m_contents == name ? FOUND : NOT_FOUND; + } + bool top_boxed_p () const override; bool bottom_boxed_p () const override; @@ -192,7 +201,15 @@ class tui_layout_split : public tui_layout_base void apply (int x, int y, int width, int height) override; - tui_adjust_result set_height (const char *name, int new_height) override; + tui_adjust_result set_height (const char *name, int new_height) override + { + return set_size<tui_layout_split::set_height_policy> (name, new_height); + } + + tui_adjust_result set_width (const char *name, int new_width) override + { + return set_size<tui_layout_split::set_width_policy> (name, new_width); + } bool top_boxed_p () const override; @@ -217,6 +234,87 @@ class tui_layout_split : public tui_layout_base private: + /* Used to implement set_height and set_width member functions. Set + either the height or width of the window named NAME to NEW_SIZE, + updating the sizes of the other windows around it as needed. The + POLICY is used to specialize this function to adjust either the height + or the width. */ + + template <class Policy> + tui_adjust_result set_size (const char *name, int new_size); + + /* A policy class for use with the set_size member function, use when we + want to adjust the height of a named window. */ + + struct set_height_policy + { + /* Set the height of window named NAME to NEW_HEIGHT in LAYOUT. */ + static tui_adjust_result + set_size (std::unique_ptr<tui_layout_base> &layout, + const char *name, + int new_height) + { + return layout->set_height (name, new_height); + } + + /* Can we adjust the heights of windows in SPLIT? */ + static bool + can_adjust (const tui_layout_split *split) + { + return split->m_vertical; + } + + /* What is the current height of LAYOUT. */ + static int + current_size (std::unique_ptr<tui_layout_base> &layout) + { + return layout->height; + } + + /* Warn about invalid height specification. */ + static void + invalid_size_warning () + { + warning (_("Invalid window height specified")); + } + }; + + /* A policy class for use with the set_size member function, use when we + want to adjust the width of a named window. */ + + struct set_width_policy + { + /* Set the width of window named NAME to NEW_HEIGHT in LAYOUT. */ + static tui_adjust_result + set_size (std::unique_ptr<tui_layout_base> &layout, + const char *name, + int new_width) + { + return layout->set_width (name, new_width); + } + + /* Can we adjust the widths of windows in SPLIT? */ + static bool + can_adjust (const tui_layout_split *split) + { + return !split->m_vertical; + } + + /* What is the current width of LAYOUT. */ + static int + current_size (std::unique_ptr<tui_layout_base> &layout) + { + return layout->width; + } + + /* Warn about invalid height specification. */ + static void + invalid_size_warning () + { + warning (_("Invalid window width specified")); + } + }; + /* Set the weights from the current heights (when m_vertical is true) or widths (when m_vertical is false). */ void set_weights_from_sizes (); @@ -266,6 +364,10 @@ extern void tui_apply_current_layout (); extern void tui_adjust_window_height (struct tui_win_info *win, int new_height); +/* Adjust the window width of WIN to NEW_WIDTH. */ +extern void tui_adjust_window_width (struct tui_win_info *win, + int new_width); + /* The type of a function that is used to create a TUI window. */ typedef std::function<tui_win_info * (const char *name)> window_factory; diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index ba6aca3d078..953af640c93 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -842,10 +842,21 @@ tui_set_tab_width_command (const char *arg, int from_tty) } } +/* Helper function for the user commands to adjust a window's width or + height. The ARG string contains the command line arguments from the + user, which should give the name of a window, and how to adjust the + size. -/* Set the height of the specified window. */ + The Policy type is used to specialise this function for updating either + the width or height of the window. + + On invalid input, or if the size can't be adjusted as requested, then an + error is thrown, otherwise, the window sizes are adjusted, and the + windows redrawn. */ + +template<typename Policy> static void -tui_set_win_height_command (const char *arg, int from_tty) +tui_set_win_size (const char *arg) { /* Make sure the curses mode is enabled. */ tui_enable (); @@ -854,7 +865,7 @@ tui_set_win_height_command (const char *arg, int from_tty) const char *buf = arg; const char *buf_ptr = buf; - int new_height; + int new_size; struct tui_win_info *win_info; buf_ptr = skip_to_space (buf_ptr); @@ -890,18 +901,82 @@ tui_set_win_height_command (const char *arg, int from_tty) if (negate) input_no *= (-1); if (fixed_size) - new_height = input_no; + new_size = input_no; else - new_height = win_info->height + input_no; + new_size = Policy::existing_window_size (win_info) + input_no; /* Now change the window's height, and adjust all other windows around it. */ - tui_adjust_window_height (win_info, new_height); + Policy::adjust_window_size (win_info, new_size); tui_update_gdb_sizes (); } else - error (_("Invalid window height specified")); + Policy::invalid_size_error (); + } +} + +/* Implement the 'tui window height' command (alias 'winheight'). */ + +static void +tui_set_win_height_command (const char *arg, int from_tty) +{ + /* Policy class for use with tui_set_win_size, this policy adjusts the + height of a window. */ + struct height_adjustment_policy + { + /* Called when the size specified is invalid. */ + static void invalid_size_error () + { + error (_("Invalid window height specified")); + } + + /* Return the existing size, height in this case, of a window WIN_INFO. */ + static int existing_window_size (struct tui_win_info *win_info) + { + return win_info->height; + } + + /* Set the size, height in this case, of WIN_INFO to NEW_SIZE. */ + static void adjust_window_size (struct tui_win_info *win_info, + int new_size) + { + tui_adjust_window_height (win_info, new_size); + } + }; + + tui_set_win_size<height_adjustment_policy> (arg); +} + +/* Implement the 'tui window width' command (alias 'winwidth'). */ + +static void +tui_set_win_width_command (const char *arg, int from_tty) +{ + /* Policy class for use with tui_set_win_size, this policy adjusts the + width of a window. */ + struct width_adjustment_policy + { + /* Called when the size specified is invalid. */ + static void invalid_size_error () + { + error (_("Invalid window width specified")); } + + /* Return the existing size, width in this case, of a window WIN_INFO. */ + static int existing_window_size (struct tui_win_info *win_info) + { + return win_info->width; + } + + /* Set the size, width in this case, of WIN_INFO to NEW_SIZE. */ + static void adjust_window_size (struct tui_win_info *win_info, + int new_size) + { + tui_adjust_window_width (win_info, new_size); + } + }; + + tui_set_win_size<width_adjustment_policy> (arg); } /* See tui-data.h. */ @@ -1033,6 +1108,16 @@ Use \"info win\" to see the names of the windows currently being displayed."), add_com_alias ("winheight", winheight_cmd, class_tui, 0); add_com_alias ("wh", winheight_cmd, class_tui, 0); set_cmd_completer (winheight_cmd, winheight_completer); + + cmd_list_element *winwidth_cmd + = add_cmd ("width", class_tui, tui_set_win_width_command, _("\ +Set or modify the width of a specified window.\n\ +Usage: tui window width WINDOW-NAME [+ | -] NUM-LINES\n\ +Use \"info win\" to see the names of the windows currently being displayed."), + &tui_window_cmds); + add_com_alias ("winwidth", winwidth_cmd, class_tui, 0); + set_cmd_completer (winwidth_cmd, winheight_completer); + add_info ("win", tui_all_windows_info, _("List of all displayed windows.\n\ Usage: info win")); ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias 2022-02-09 15:33 ` Andrew Burgess @ 2022-02-09 17:03 ` Eli Zaretskii 0 siblings, 0 replies; 74+ messages in thread From: Eli Zaretskii @ 2022-02-09 17:03 UTC (permalink / raw) To: Andrew Burgess; +Cc: gdb-patches > From: Andrew Burgess <aburgess@redhat.com> > Cc: gdb-patches@sourceware.org > Date: Wed, 09 Feb 2022 15:33:30 +0000 > > > Btw, should we mention that this new command will only have effect if > > more than one window is displayed? > > What about this for the description of 'tui window width'? The second > paragraph is new: It's fine, thanks. > If this is OK, then I would propose adding the same paragraph to the > description of 'tui window height' which obviously has the same > restrictions. Right. ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias 2022-02-06 14:12 ` [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess 2022-02-06 15:52 ` Eli Zaretskii @ 2022-03-03 18:52 ` Pedro Alves 1 sibling, 0 replies; 74+ messages in thread From: Pedro Alves @ 2022-03-03 18:52 UTC (permalink / raw) To: Andrew Burgess, gdb-patches On 2022-02-06 14:12, Andrew Burgess via Gdb-patches wrote: > As for the changes in gdb itself, I've mostly just templated the > existing height adjustment code so that the two functions > tui_layout_split::adjust_size (tui-layout.c) and > tui_set_win_height_command (tui-win.c) now have a template parameter > "policy", this policy allows me to specialise the functions for either > width or height adjustment. Function arguments, and locals, are > renamed, replacing 'height' with 'size'. Do you envision that there will be more policies going forward, other than width and height? Template policies are a good thing when the number of policies is open ended, such as with library utility classes where you want the user of the utility be able to configure your type. But here, you only have two modes of operation and they are totally known upfront, which seems like could be just as well handled with a bool or enum. The disadvantage of the policy approach is that leads to code bloat, as the compiler basically duplicates the functions. ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 06/15] gdb/tui: add a tui debugging flag 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (4 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-02-06 15:53 ` Eli Zaretskii 2022-03-04 16:35 ` Tom Tromey 2022-02-06 14:12 ` [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess ` (10 subsequent siblings) 16 siblings, 2 replies; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit adds 'set debug tui on|off' and 'show debug tui'. This commit adds the control variable, and the printing macros in tui/tui.h. I've then added some uses of these in tui.c and tui-layout.c. To help produce more useful debug output in tui-layout.c, I've added some helper member functions in the class tui_layout_split, and also moved the size_info struct out of tui_layout_split::apply into the tui_layout_split class. If tui debug is not turned on, then there should be no user visible changes after this commit. One thing to note is that, due to the way that the tui terminal is often cleared, the only way I've found this useful is when I do: (gdb) tui enable (gdb) set logging file /path/to/file (gdb) set logging debugredirect on (gdb) set logging enable on Additionally, gdb has some quirks when it comes to setting up logging redirect and switching interpreters. Thus, the above only really works if the logging is enabled after the tui is enabled, and disabled again before the tui is disabled. Enabling logging and switching interpreters can cause undefined results, including crashes. This is an existing bug in gdb, and has nothing directly to do with tui debug, but it is worth mentioning here I think. --- gdb/NEWS | 4 ++ gdb/doc/gdb.texinfo | 11 +++++ gdb/tui/tui-layout.c | 99 +++++++++++++++++++++++++++++++++++++++----- gdb/tui/tui-layout.h | 25 +++++++++++ gdb/tui/tui.c | 26 ++++++++++++ gdb/tui/tui.h | 14 +++++++ 6 files changed, 168 insertions(+), 11 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 1faef78056a..73d5548ba19 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -95,6 +95,10 @@ winwidth the width of a tui window to be adjusted when windows are laid out in horizontal mode. +set debug tui on|off +show debug tui + Control the display of debug output about GDB's tui. + * Changed commands maint packet diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 4793a054f7e..47fbb8d78b1 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -29055,6 +29055,17 @@ source text at the next tab stop; the compact display uses only as much space as is needed for the line numbers in the current file, and only a single space to separate the line numbers from the source. + +@kindex set debug tui +@item set debug tui @r{[}on|off@r{]} +Turn on or off display of @value{GDBN} internal debug messages relating +to the TUI. + +@kindex show debug tui +@item show debug tui +Show the current status of displaying @value{GDBN} internal debug +messages relating to the TUI. + @end table Note that the colors of the TUI borders can be controlled using the diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 13e4d462426..1ce912b3cdb 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -426,8 +426,14 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_) void tui_layout_window::get_sizes (bool height, int *min_value, int *max_value) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + if (m_window == nullptr) m_window = tui_get_window_by_name (m_contents); + + tui_debug_printf ("window = %s, getting %s", + m_window->name (), (height ? "height" : "width")); + if (height) { *min_value = m_window->min_height (); @@ -438,6 +444,8 @@ tui_layout_window::get_sizes (bool height, int *min_value, int *max_value) *min_value = m_window->min_width (); *max_value = m_window->max_width (); } + + tui_debug_printf ("min = %d, max = %d", *min_value, *max_value); } /* See tui-layout.h. */ @@ -522,6 +530,8 @@ tui_layout_split::clone () const void tui_layout_split::get_sizes (bool height, int *min_value, int *max_value) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + *min_value = 0; *max_value = 0; bool first_time = true; @@ -544,6 +554,8 @@ tui_layout_split::get_sizes (bool height, int *min_value, int *max_value) } first_time = false; } + + tui_debug_printf ("min_value = %d, max_value = %d", *min_value, *max_value); } /* See tui-layout.h. */ @@ -578,10 +590,47 @@ tui_layout_split::set_weights_from_sizes () /* See tui-layout.h. */ +std::string +tui_layout_split::tui_debug_weights_to_string () const +{ + std::string str; + + for (int i = 0; i < m_splits.size (); ++i) + { + if (i > 0) + str += ", "; + str += string_printf ("[%d] %d", i, m_splits[i].weight); + } + + return str; +} + +/* See tui-layout.h. */ + +void +tui_layout_split::tui_debug_print_size_info + (const std::vector<tui_layout_split::size_info> &info) +{ + gdb_assert (debug_tui); + + tui_debug_printf ("current size info data:"); + for (int i = 0; i < info.size (); ++i) + tui_debug_printf (" [%d] { size = %d, min = %d, max = %d, share_box = %d }", + i, info[i].size, info[i].min_size, + info[i].max_size, info[i].share_box); +} + +/* See tui-layout.h. */ + template<class Policy> tui_adjust_result tui_layout_split::set_size (const char *name, int new_size) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + + tui_debug_printf ("this = %p, name = %s, new_size = %d", + this, name, new_size); + /* Look through the children. If one is a layout holding the named window, we're done; or if one actually is the named window, update it. */ @@ -606,10 +655,15 @@ tui_layout_split::set_size (const char *name, int new_size) if (Policy::current_size (m_splits[found_index].layout) == new_size) return HANDLED; + tui_debug_printf ("found window %s at index %d", name, found_index); + set_weights_from_sizes (); int delta = m_splits[found_index].weight - new_size; m_splits[found_index].weight = new_size; + tui_debug_printf ("before delta (%d) distribution, weights: %s", + delta, tui_debug_weights_to_string ().c_str ()); + /* Distribute the "delta" over the next window; but if the next window cannot hold it all, keep going until we either find a window that does, or until we loop all the way around. */ @@ -638,8 +692,14 @@ tui_layout_split::set_size (const char *name, int new_size) m_splits[index].weight += grow_by; delta -= grow_by; } + + tui_debug_printf ("index = %d, weight now: %d", + index, m_splits[index].weight); } + tui_debug_printf ("after delta (%d) distribution, weights: %s", + delta, tui_debug_weights_to_string ().c_str ()); + if (delta != 0) { Policy::invalid_size_warning (); @@ -660,23 +720,18 @@ tui_layout_split::set_size (const char *name, int new_size) void tui_layout_split::apply (int x_, int y_, int width_, int height_) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + x = x_; y = y_; width = width_; height = height_; - struct size_info - { - int size; - int min_size; - int max_size; - /* True if this window will share a box border with the previous - window in the list. */ - bool share_box; - }; - std::vector<size_info> info (m_splits.size ()); + tui_debug_printf ("weights are: %s", + tui_debug_weights_to_string ().c_str ()); + /* Step 1: Find the min and max size of each sub-layout. Fixed-sized layouts are given their desired size, and then the remaining space is distributed among the remaining windows @@ -752,9 +807,31 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) } } + if (debug_tui) + { + tui_debug_printf ("after initial size calculation"); + tui_debug_printf ("available_size = %d, used_size = %d", + available_size, used_size); + tui_debug_printf ("total_weight = %d, last_index = %d", + total_weight, last_index); + tui_debug_print_size_info (info); + } + /* Allocate any leftover size. */ if (available_size >= used_size && last_index != -1) - info[last_index].size += available_size - used_size; + { + info[last_index].size += available_size - used_size; + + if (debug_tui) + { + tui_debug_printf ("after final size calculation"); + tui_debug_printf ("available_size = %d, used_size = %d", + available_size, used_size); + tui_debug_printf ("total_weight = %d, last_index = %d", + total_weight, last_index); + tui_debug_print_size_info (info); + } + } /* Step 3: Resize. */ int size_accum = 0; diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index f4ef0895f1f..ebfcae74356 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -319,6 +319,31 @@ class tui_layout_split : public tui_layout_base widths (when m_vertical is false). */ void set_weights_from_sizes (); + /* Structure used when resizing, or applying a layout. An instance of + this structure is created for each sub-layout. */ + struct size_info + { + /* The calculated size for this sub-layout. */ + int size; + + /* The minimum and maximum sizes for this sub-layout, obtained by + calling the get_sizes member function. */ + int min_size; + int max_size; + + /* True if this window will share a box border with the previous + window in the list. */ + bool share_box; + }; + + /* Used for debug, prints the contents of INFO using tui_debug_printf. + Only call this when the global debug_tui is true. */ + static void tui_debug_print_size_info (const std::vector<size_info> &info); + + /* Used for debug, returns a string describing the current weight of each + sub-layout. */ + std::string tui_debug_weights_to_string () const; + struct split { /* The requested weight. */ diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c index 776dccf0bb2..6332eceb4af 100644 --- a/gdb/tui/tui.c +++ b/gdb/tui/tui.c @@ -50,6 +50,19 @@ #include "gdb_curses.h" #include "interps.h" +/* See tui.h. */ + +bool debug_tui = false; + +/* Implement 'show debug tui'. */ + +static void +show_tui_debug (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("TUI debugging is \"%s\".\n"), value); +} + /* This redefines CTRL if it is not already defined, so it must come after terminal state releated include files like <term.h> and "gdb_curses.h". */ @@ -354,6 +367,8 @@ gdb_getenv_term (void) void tui_enable (void) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + if (tui_active) return; @@ -494,6 +509,8 @@ tui_enable (void) void tui_disable (void) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + if (!tui_active) return; @@ -587,4 +604,13 @@ Usage: tui enable"), _("Disable TUI display mode.\n\ Usage: tui disable"), tuicmd); + + /* Debug this tui internals. */ + add_setshow_boolean_cmd ("tui", class_maintenance, &debug_tui, _("\ +Set tui debugging."), _("\ +Show tui debugging."), _("\ +When true, tui specific internal debugging is enabled."), + NULL, + show_tui_debug, + &setdebuglist, &showdebuglist); } diff --git a/gdb/tui/tui.h b/gdb/tui/tui.h index a4df66f17fc..924d91daa7e 100644 --- a/gdb/tui/tui.h +++ b/gdb/tui/tui.h @@ -22,6 +22,20 @@ #ifndef TUI_TUI_H #define TUI_TUI_H +/* Flag to control tui debugging. */ + +extern bool debug_tui; + +/* Print a "tui" debug statement. */ + +#define tui_debug_printf(fmt, ...) \ + debug_prefixed_printf_cond (debug_tui, "tui", fmt, ##__VA_ARGS__) + +/* Print "tui" enter/exit debug statements. */ + +#define TUI_SCOPED_DEBUG_ENTER_EXIT \ + scoped_debug_enter_exit (debug_tui, "tui") + struct ui_file; /* Types of error returns. */ -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 06/15] gdb/tui: add a tui debugging flag 2022-02-06 14:12 ` [PATCHv2 06/15] gdb/tui: add a tui debugging flag Andrew Burgess @ 2022-02-06 15:53 ` Eli Zaretskii 2022-03-04 16:35 ` Tom Tromey 1 sibling, 0 replies; 74+ messages in thread From: Eli Zaretskii @ 2022-02-06 15:53 UTC (permalink / raw) To: Andrew Burgess; +Cc: gdb-patches > Date: Sun, 6 Feb 2022 14:12:44 +0000 > From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> > Cc: Andrew Burgess <aburgess@redhat.com> > > gdb/NEWS | 4 ++ > gdb/doc/gdb.texinfo | 11 +++++ > gdb/tui/tui-layout.c | 99 +++++++++++++++++++++++++++++++++++++++----- > gdb/tui/tui-layout.h | 25 +++++++++++ > gdb/tui/tui.c | 26 ++++++++++++ > gdb/tui/tui.h | 14 +++++++ > 6 files changed, 168 insertions(+), 11 deletions(-) Thanks, the documentation parts are okay. ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 06/15] gdb/tui: add a tui debugging flag 2022-02-06 14:12 ` [PATCHv2 06/15] gdb/tui: add a tui debugging flag Andrew Burgess 2022-02-06 15:53 ` Eli Zaretskii @ 2022-03-04 16:35 ` Tom Tromey 1 sibling, 0 replies; 74+ messages in thread From: Tom Tromey @ 2022-03-04 16:35 UTC (permalink / raw) To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess Andrew> Enabling logging and switching interpreters can cause undefined Andrew> results, including crashes. This is an existing bug in gdb, and has Andrew> nothing directly to do with tui debug, but it is worth mentioning here Andrew> I think. Is this in bugzilla already? Tom ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (5 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 06/15] gdb/tui: add a tui debugging flag Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-03-04 16:37 ` Tom Tromey 2022-02-06 14:12 ` [PATCHv2 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess ` (9 subsequent siblings) 16 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess When I initially saw this code in tui_layout_split::apply, I assumed that this must be a bug: /* Two adjacent boxed windows will share a border, making a bit more size available. */ if (i > 0 && m_splits[i - 1].layout->bottom_boxed_p () && m_splits[i].layout->top_boxed_p ()) ... After all, the apply might be laying out a horizontal layout, right, so checking bottom_boxed_p and top_boxed_p is clearly wrong. Well, turns on, that due to the implementations of these things, bottom_boxed_p is equivalent to an imagined right_boxed_p, and top_boxed_p is equivalent to an imagined left_boxed_p. I did consider just adding a comment about this to the above code, but this still doesn't feel great. So, in this commit, I've just filled in the API to add right_boxed_p and left_boxed_p, and now I call these instead of bottom_boxed_p and top_boxed_p if appropriate. Maybe it's just pointless noise.... ... I'd rather the main apply function not have to have special knowledge about the implementation of these things coded into it. There should be no user visible changes after this commit. --- gdb/tui/tui-layout.c | 46 ++++++++++++++++++++++++++++++++++++++++++-- gdb/tui/tui-layout.h | 14 ++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 1ce912b3cdb..ca901e5c85d 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -468,6 +468,24 @@ tui_layout_window::bottom_boxed_p () const /* See tui-layout.h. */ +bool +tui_layout_window::left_boxed_p () const +{ + gdb_assert (m_window != nullptr); + return m_window->can_box (); +} + +/* See tui-layout.h. */ + +bool +tui_layout_window::right_boxed_p () const +{ + gdb_assert (m_window != nullptr); + return m_window->can_box (); +} + +/* See tui-layout.h. */ + void tui_layout_window::replace_window (const char *name, const char *new_window) { @@ -580,6 +598,26 @@ tui_layout_split::bottom_boxed_p () const /* See tui-layout.h. */ +bool +tui_layout_split::left_boxed_p () const +{ + if (m_splits.empty ()) + return false; + return m_splits[0].layout->left_boxed_p (); +} + +/* See tui-layout.h. */ + +bool +tui_layout_split::right_boxed_p () const +{ + if (m_splits.empty ()) + return false; + return m_splits.back ().layout->right_boxed_p (); +} + +/* See tui-layout.h. */ + void tui_layout_split::set_weights_from_sizes () { @@ -777,8 +815,12 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) /* Two adjacent boxed windows will share a border, making a bit more size available. */ if (i > 0 - && m_splits[i - 1].layout->bottom_boxed_p () - && m_splits[i].layout->top_boxed_p ()) + && ((m_vertical + && m_splits[i - 1].layout->bottom_boxed_p () + && m_splits[i].layout->top_boxed_p ()) + || (!m_vertical + && m_splits[i - 1].layout->right_boxed_p () + && m_splits[i].layout->left_boxed_p ()))) info[i].share_box = true; } diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index ebfcae74356..e160eaa2256 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -68,6 +68,12 @@ class tui_layout_base /* True if the bottommost item in this layout is boxed. */ virtual bool bottom_boxed_p () const = 0; + /* True if the leftmost item in this layout is boxed. */ + virtual bool left_boxed_p () const = 0; + + /* True if the rightmost item in this layout is boxed. */ + virtual bool right_boxed_p () const = 0; + /* Return the name of this layout's window, or nullptr if this layout does not represent a single window. */ virtual const char *get_name () const @@ -145,6 +151,10 @@ class tui_layout_window : public tui_layout_base bool bottom_boxed_p () const override; + bool left_boxed_p () const override; + + bool right_boxed_p () const override; + void remove_windows (const char *name) override { } @@ -215,6 +225,10 @@ class tui_layout_split : public tui_layout_base bool bottom_boxed_p () const override; + bool left_boxed_p () const override; + + bool right_boxed_p () const override; + void remove_windows (const char *name) override; void replace_window (const char *name, const char *new_window) override; -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions 2022-02-06 14:12 ` [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess @ 2022-03-04 16:37 ` Tom Tromey 0 siblings, 0 replies; 74+ messages in thread From: Tom Tromey @ 2022-03-04 16:37 UTC (permalink / raw) To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess >>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes: Andrew> I did consider just adding a comment about this to the above code, but Andrew> this still doesn't feel great. So, in this commit, I've just filled Andrew> in the API to add right_boxed_p and left_boxed_p, and now I call these Andrew> instead of bottom_boxed_p and top_boxed_p if appropriate. Andrew> Maybe it's just pointless noise.... Andrew> ... I'd rather the main apply function not have to have special Andrew> knowledge about the implementation of these things coded into it. It seems fine but I wonder if just renaming these methods would yield the same effective result without duplicating code. Tom ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 08/15] gdb/tui/testsuite: refactor new-layout.exp test 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (6 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess ` (8 subsequent siblings) 16 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit changes the gdb.tui/new-layout.exp test to make use of a list of test descriptions, and a loop to check each description in turn. There's no change to what is actually tested after this commit. In future commits I plan to add additional tests to this file, and this will be easier now that all I have to do is add a new test description to the list. --- gdb/testsuite/gdb.tui/new-layout.exp | 83 +++++++++++++++++++--------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index 2b5e07db612..d3d34af7439 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -55,20 +55,39 @@ if { [tcl_version_at_least 8 6] } { "Missing '\}' in layout specification" } -gdb_test_no_output "tui new-layout example asm 1 status 0 cmd 1" - -gdb_test "help layout example" \ - "Apply the \"example\" layout.*tui new-layout example asm 1 status 0 cmd 1" - -gdb_test_no_output "tui new-layout example2 {asm 1 status 0} 1 cmd 1" - -gdb_test "help layout example2" \ - "Apply the \"example2\" layout.*tui new-layout example2 {asm 1 status 0} 1 cmd 1" - -gdb_test_no_output "tui new-layout h {-horizontal asm 1 src 1} 1 status 0 cmd 1" +# Each entry of this list describes a layout, and some associated +# tests. The items within each entry are: +# 1. layout name, +# 2. a string used to create the layout, +# 3. a list of boxes to check for once the layout is selected, +# 4. a regexp to match against the whole screen contents, this +# can be empty to skip this check. +set layouts \ + [list \ + [list example "asm 1 status 0 cmd 1" \ + {{0 0 80 15}} "$hex <main>"] \ + [list example2 "{asm 1 status 0} 1 cmd 1" \ + {{0 0 80 15}} ""] \ + [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \ + {{0 0 40 15} {39 0 41 15}} \ + "$hex <main>.*21.*return 0"]] + +# Helper function to verify a list of boxes. +proc check_boxes {boxes} { + set boxno 1 + foreach box $boxes { + eval Term::check_box [list "box $boxno"] $box + incr boxno + } +} -gdb_test "help layout h" \ - "Apply the \"h\" layout.*tui new-layout h {-horizontal asm 1 src 1} 1 status 0 cmd 1" +# Now create the layouts. +foreach layout $layouts { + lassign $layout name desc + gdb_test_no_output "tui new-layout $name $desc" + gdb_test "help layout $name" \ + "Apply the \"$name\" layout.*tui new-layout $name $desc" +} if {![Term::enter_tui]} { unsupported "TUI not supported" @@ -79,20 +98,30 @@ set text [Term::get_all_lines] gdb_assert {![string match "No Source Available" $text]} \ "initial source listing" -Term::command "layout example" -Term::check_contents "example layout shows assembly" \ - "$hex <main>" +foreach_with_prefix layout $layouts { + lassign $layout name desc boxes content_pattern + + # Reset the layout to a known starting configuration. + Term::command "layout src" + Term::command "winheight cmd 8" + + # Apply our test layout. + Term::command "layout $name" + check_boxes $boxes -Term::command "layout h" -Term::check_box "left window box" 0 0 40 15 -Term::check_box "right window box" 39 0 41 15 -Term::check_contents "horizontal display" \ - "$hex <main>.*21.*return 0" + if {$content_pattern != ""} { + Term::check_contents "contents in layout $name" \ + "${content_pattern}" + } -Term::command "winheight src - 5" -Term::check_box "left window box after shrink" 0 0 40 10 -Term::check_box "right window box after shrink" 39 0 41 10 + # Some additional tests for the 'h' layout. + if {$name == "h"} { + Term::command "winheight src - 5" + Term::check_box "left window box after shrink" 0 0 40 10 + Term::check_box "right window box after shrink" 39 0 41 10 -Term::command "winheight src + 5" -Term::check_box "left window box after grow" 0 0 40 15 -Term::check_box "right window box after grow" 39 0 41 15 + Term::command "winheight src + 5" + Term::check_box "left window box after grow" 0 0 40 15 + Term::check_box "right window box after grow" 39 0 41 15 + } +} -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 09/15] gdb/tui: avoid fp exception when applying layouts 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (7 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess ` (7 subsequent siblings) 16 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess Consider: (gdb) tui enable (gdb) layout src (gdb) tui new-layout conly cmd 1 (gdb) layout conly After this, with current master, gdb crashes with a floating-point exception. The problem is that in tui_layout_split::apply, when we switch from 'src' to 'conly', we will try to retain the cmd window height. As such, the cmd window will become a fixed size window, which decreases the available_size, but doesn't count towards the total_weight. As the cmd window is the only window, the total_weight stays at zero, and, when we move into step 2, where we attempt to size the windows, we perform a divide by zero, and crash. After this commit we avoid the divide by zero, and just directly set the window size based on the fixed size. There is still a problem after this commit, when the conly layout is selected the cmd window retains its original height, which will only be part of the terminal. The rest of the terminal is left unused. This issue will be addressed in a later commit, this commit is just about the floating-point exception. --- gdb/testsuite/gdb.tui/new-layout.exp | 3 ++- gdb/tui/tui-layout.c | 30 ++++++++++++++++++---------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index d3d34af7439..66048e65238 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -70,7 +70,8 @@ set layouts \ {{0 0 80 15}} ""] \ [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \ {{0 0 40 15} {39 0 41 15}} \ - "$hex <main>.*21.*return 0"]] + "$hex <main>.*21.*return 0"] \ + [list cmd_only "cmd 1" {} ""]] # Helper function to verify a list of boxes. proc check_boxes {boxes} { diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index ca901e5c85d..1de34c34e62 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -824,29 +824,37 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) info[i].share_box = true; } + /* If last_index is set then we have a window that is not of a fixed + size. This window will have its size calculated below, which requires + that the total_weight not be zero (we divide by total_weight, so don't + want a floating-point exception). */ + gdb_assert (last_index == -1 || total_weight > 0); + /* Step 2: Compute the size of each sub-layout. Fixed-sized items are given their fixed size, while others are resized according to their weight. */ int used_size = 0; for (int i = 0; i < m_splits.size (); ++i) { - /* Compute the height and clamp to the allowable range. */ - info[i].size = available_size * m_splits[i].weight / total_weight; - if (info[i].size > info[i].max_size) - info[i].size = info[i].max_size; - if (info[i].size < info[i].min_size) - info[i].size = info[i].min_size; - /* If there is any leftover size, just redistribute it to the - last resizeable window, by dropping it from the allocated - size. We could try to be fancier here perhaps, by - redistributing this size among all windows, not just the - last window. */ if (info[i].min_size != info[i].max_size) { + /* Compute the height and clamp to the allowable range. */ + info[i].size = available_size * m_splits[i].weight / total_weight; + if (info[i].size > info[i].max_size) + info[i].size = info[i].max_size; + if (info[i].size < info[i].min_size) + info[i].size = info[i].min_size; + /* If there is any leftover size, just redistribute it to the + last resizeable window, by dropping it from the allocated + size. We could try to be fancier here perhaps, by + redistributing this size among all windows, not just the + last window. */ used_size += info[i].size; if (info[i].share_box) --used_size; } + else + info[i].size = info[i].min_size; } if (debug_tui) -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (8 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-03-04 16:42 ` Tom Tromey 2022-02-06 14:12 ` [PATCHv2 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess ` (6 subsequent siblings) 16 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess When applying layouts gdb computes the size of each window (or rather, each sub-layout within a layout) using integer arithmetic. As this rounds down the results, then, when all sub-layouts are sized, there is the possibility that we have some space left over. Currently, this space is just assigned to an arbitrary sub-layout. This can result in some unbalanced results. Consider this set of steps with current master: (gdb) tui enable (gdb) layout regs (gdb) info win Name Lines Columns Focus regs 7 80 src 9 80 (has focus) status 1 80 cmd 8 80 Notice the weird split between the src and regs windows, the original layout specification has these windows given equal weight. The problem is that, with rounding, both the regs and src windows are initially sized to 7, the extra 2 lines are then arbitrarily added to the src window. In this commit, rather than add all the extra space to one single window, I instead hand out the extra space 1 line at a time, looping over all the sub-layouts. We take care to respect the min/max sizes, and so, we now get this result: (gdb) tui enable (gdb) layout regs (gdb) info win Name Lines Columns Focus regs 8 80 src 8 80 (has focus) status 1 80 cmd 8 80 This looks more natural to me. This is obviously a change in behaviour, and so, lots of the existing tests need to be updated to take this into account. None of the changes are huge, it's just a line or two (or column for width) moved between windows. --- gdb/testsuite/gdb.tui/basic.exp | 4 ++-- gdb/testsuite/gdb.tui/empty.exp | 14 +++++++++----- gdb/testsuite/gdb.tui/regs.exp | 4 ++-- gdb/testsuite/gdb.tui/winwidth.exp | 17 +++++++++-------- gdb/tui/tui-layout.c | 28 ++++++++++++++++++++++++++-- 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/gdb/testsuite/gdb.tui/basic.exp b/gdb/testsuite/gdb.tui/basic.exp index 0e9f2e3eab2..7afb28b0858 100644 --- a/gdb/testsuite/gdb.tui/basic.exp +++ b/gdb/testsuite/gdb.tui/basic.exp @@ -104,5 +104,5 @@ Term::command "layout split" Term::check_contents "split layout contents" \ "$main_line *$main_re.*$hex <main>" -Term::check_box "source box in split layout" 0 0 80 7 -Term::check_box "asm box in split layout" 0 6 80 9 +Term::check_box "source box in split layout" 0 0 80 8 +Term::check_box "asm box in split layout" 0 7 80 8 diff --git a/gdb/testsuite/gdb.tui/empty.exp b/gdb/testsuite/gdb.tui/empty.exp index ef14fe4dac0..3efa55d812e 100644 --- a/gdb/testsuite/gdb.tui/empty.exp +++ b/gdb/testsuite/gdb.tui/empty.exp @@ -35,26 +35,26 @@ if {![Term::enter_tui]} { set layouts { {src src {{0 0 80 15}} {{0 0 90 26}} {{"no source" "No Source Available"}}} - {regs src-regs {{0 0 80 7} {0 6 80 9}} {{0 0 90 13} {0 12 90 13}} + {regs src-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}} { {"no source" "No Source Available"} {"no regs" "Register Values Unavailable"} }} - {asm asm {{0 0 80 13}} {{0 0 90 26}} + {asm asm {{0 0 80 15}} {{0 0 90 26}} { {"no asm" "No Assembly Available"} }} - {regs asm-regs {{0 0 80 7} {0 6 80 9}} {{0 0 90 13} {0 12 90 13}} + {regs asm-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}} { {"no asm" "No Assembly Available"} {"no regs" "Register Values Unavailable"} }} - {split split {{0 0 80 6} {0 5 80 8}} {{0 0 90 13} {0 12 90 13}} + {split split {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}} { {"no source" "No Source Available"} {"no asm" "No Assembly Available"} }} - {regs split-regs {{0 0 80 6} {0 5 80 8}} {{0 0 90 13} {0 12 90 13}} + {regs split-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}} { {"no asm" "No Assembly Available"} {"no regs" "Register Values Unavailable"} @@ -97,5 +97,9 @@ foreach layout $layouts { check_text $text_list } Term::resize 24 80 + with_test_prefix "80x24 again" { + check_boxes $small_boxes + check_text $text_list + } } } diff --git a/gdb/testsuite/gdb.tui/regs.exp b/gdb/testsuite/gdb.tui/regs.exp index 178eba03f19..2f3482f5d38 100644 --- a/gdb/testsuite/gdb.tui/regs.exp +++ b/gdb/testsuite/gdb.tui/regs.exp @@ -38,8 +38,8 @@ if {![Term::enter_tui]} { Term::check_contents "source at startup" "\\|.*21 *return 0" Term::command "layout regs" -Term::check_box "register box" 0 0 80 7 -Term::check_box "source box in regs layout" 0 6 80 9 +Term::check_box "register box" 0 0 80 8 +Term::check_box "source box in regs layout" 0 7 80 8 set text [Term::get_line 1] # Just check for any register window content at all. diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp index b0a838b578f..1767b25c8d3 100644 --- a/gdb/testsuite/gdb.tui/winwidth.exp +++ b/gdb/testsuite/gdb.tui/winwidth.exp @@ -39,24 +39,25 @@ with_test_prefix "original window sizes" { } with_test_prefix "after src +5" { - Term::check_box "source box" 0 0 44 15 - Term::check_box "asm box" 43 0 37 15 + Term::check_box "source box" 0 0 45 15 + Term::check_box "asm box" 44 0 36 15 Term::command "winwidth asm -5" } with_test_prefix "after asm -5" { - Term::check_box "source box" 0 0 48 15 - Term::check_box "asm box" 47 0 33 15 + Term::dump_screen + Term::check_box "source box" 0 0 50 15 + Term::check_box "asm box" 49 0 31 15 Term::command "winwidth asm +8" } with_test_prefix "after asm +8" { - Term::check_box "source box" 0 0 39 15 - Term::check_box "asm box" 38 0 42 15 + Term::check_box "source box" 0 0 42 15 + Term::check_box "asm box" 41 0 39 15 Term::command "winwidth src -2" } with_test_prefix "after src -2" { - Term::check_box "source box" 0 0 36 15 - Term::check_box "asm box" 35 0 45 15 + Term::check_box "source box" 0 0 40 15 + Term::check_box "asm box" 39 0 41 15 } diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 1de34c34e62..8ba54a68fab 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -868,9 +868,33 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) } /* Allocate any leftover size. */ - if (available_size >= used_size && last_index != -1) + if (available_size > used_size && last_index != -1) { - info[last_index].size += available_size - used_size; + /* Loop over all windows until all available space is used up. */ + bool found_window_that_can_grow_p = true; + for (int idx = last_index; + available_size > used_size; + idx = (idx + 1) % m_splits.size ()) + { + /* Once we have visited all of the windows, check that we did + manage to allocate some more space. This prevents us getting + stuck in the loop forever if we can't allocate anything + more. */ + if (idx == last_index) + { + if (!found_window_that_can_grow_p) + break; + found_window_that_can_grow_p = false; + } + + if (available_size > used_size + && info[idx].size < info[idx].max_size) + { + found_window_that_can_grow_p = true; + info[idx].size += 1; + used_size += 1; + } + } if (debug_tui) { -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply 2022-02-06 14:12 ` [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess @ 2022-03-04 16:42 ` Tom Tromey 0 siblings, 0 replies; 74+ messages in thread From: Tom Tromey @ 2022-03-04 16:42 UTC (permalink / raw) To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess >>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes: Andrew> In this commit, rather than add all the extra space to one single Andrew> window, I instead hand out the extra space 1 line at a time, looping Andrew> over all the sub-layouts. We take care to respect the min/max sizes, Andrew> and so, we now get this result: I think this patch should also update this comment a bit earlier in the function: /* If there is any leftover size, just redistribute it to the last resizeable window, by dropping it from the allocated size. We could try to be fancier here perhaps, by redistributing this size among all windows, not just the last window. */ ... because now the fancier thing is done. I'm not sure any more if this comment correctly explains the following 'if', so I don't know if the comment can just be removed or if it needs some kind of rewording. Tom ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (9 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess ` (5 subsequent siblings) 16 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess When we switch layouts we call the tui_layout_split::apply member function to reapply the layout, and recalculate all the window sizes. One special case is the cmd window, which we try to keep at its existing size. However, in some cases it is not appropriate to keep the cmd window at its existing size. I will describe two such cases here, in one, we want the cmd window to reduce in size, and in the other, we want the cmd window to grow in size. Try these steps in a 80 columns, by 24 lines terminal: (gdb) tui enable (gdb) layout src (gdb) winheight cmd 20 (gdb) layout split You should see that the status window is missing from the new layout, and that the cmd window has been placed over the border of the asm window. The 'info win' output is: (gdb) info win Name Lines Columns Focus src 3 80 (has focus) asm 3 80 status 1 80 cmd 20 80 Notice that gdb has assigned 27 lines of screen space, even with the border overlap between the src and asm windows, this is still 2 lines too many. The problem here is that after switching layouts, gdb has forced the cmd window to retain its 20 line height. Really, we want the cmd window to reduce in height so that the src and asm windows can occupy their minimum required space. This commit allows this (details on how are below). After this commit, in the above situation, we now see the status window displayed correctly, and the 'info win' output is: (gdb) info win Name Lines Columns Focus src 3 80 (has focus) asm 3 80 status 1 80 cmd 18 80 The cmd window has been reduced in size by 2 lines so that everything can fit on the screen. The second example is one which was discussed in a recent commit, consider this case (still in the 80 column, 24 line terminal): (gdb) tui enable (gdb) tui new-layout conly cmd 1 (gdb) layout conly (gdb) info win Name Lines Columns Focus cmd 8 80 (has focus) (gdb) This layout only contains a cmd window, which we would expect to occupy the entire terminal. But instead, the cmd window only occupies the first 8 lines, and the rest of the terminal is unused! The reason is, again, that the cmd window is keeping its previous size (8 lines). After this commit things are slightly different, the 'info win' output is now: (gdb) info win Name Lines Columns Focus cmd 20 80 (has focus) Which is a little better, but why only 20 lines? Turns out there's yet another bug hitting this case. That bug will be addressed in a later commit, so, for now, we're accepting the 20 lines. What this commit does is modify the phase of tui_layout_split::apply that handles any left over space. Usually, in "Step 2", each sub-layout has a size calculated. As the size is an integer, then, when all sizes are calculated we may have some space left over. This extra space is then distributed between all the windows fairly until all the space is used up. When we consider windows minimum size, or fixed size windows, then it is possible that we might try to use more space than is available, this was our first example above. The same code that added extra space to the windows, can also be used to reclaim space (in the over allocation case) to allow all windows to fit. The problem then is the cmd window, which we often force to a fixed size. Inside the loop that handles the allocation of excess space, if we find that we have tried every window, and still have space either left to give, or we need to claim back more space, then, if the cmd window was changed to a fixed size, we can change the cmd window back to a non-fixed-size window, and proceed to either give, or take space from the cmd window as needed. --- gdb/testsuite/gdb.tui/new-layout.exp | 9 +++ gdb/testsuite/gdb.tui/winheight.exp | 46 ++++++++++++++ gdb/tui/tui-layout.c | 95 +++++++++++++++++++++++++--- 3 files changed, 142 insertions(+), 8 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index 66048e65238..0d49d033be5 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -124,5 +124,14 @@ foreach_with_prefix layout $layouts { Term::command "winheight src + 5" Term::check_box "left window box after grow" 0 0 40 15 Term::check_box "right window box after grow" 39 0 41 15 + } elseif {$name == "cmd_only"} { + Term::check_region_contents "bottom of cmd window is blank" \ + 0 14 80 10 "^\\s+$" + Term::command "info win" + Term::check_region_contents "info win output" \ + 0 0 80 24 [multi_line "info win\\s+" \ + "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \ + "cmd\\s+20\\s+80\\s+\\(has focus\\)\\s+" \ + "$gdb_prompt\\s+"] } } diff --git a/gdb/testsuite/gdb.tui/winheight.exp b/gdb/testsuite/gdb.tui/winheight.exp index 0d0c886304d..b541c21b825 100644 --- a/gdb/testsuite/gdb.tui/winheight.exp +++ b/gdb/testsuite/gdb.tui/winheight.exp @@ -50,3 +50,49 @@ Term::check_box "larger source box again" 0 0 80 15 Term::command "layout asm" Term::check_box "check for asm window" 0 0 80 15 + +# Check what happens when we switch from src layout to split layout. +# The interesting thing here is that the src layout has one flexible +# window (the src), the status window, which is of fixed size, and the +# cmd window, which tries to retain its size when a layout changes. +# +# In contrast, the split layout has both a src and asm window, plus +# the same status and cmd windows. +# +# Of particular interest here is the first test, where we maximise the +# cmd window before switching to split. This requires gdb to realise +# that it has to shrink the cmd window, even though this is something +# gdb usually avoids doing. +# +# Each test here is a size for the src window in the 'src' layout. +# The test then switches to the 'split' layout, and calculates the +# expected window sizes. +foreach_with_prefix cmd_size {20 12 5} { + set src_size_before [expr 24 - ${cmd_size} - 1] + set split_size [expr (24 - ${cmd_size}) / 2] + + if { $split_size < 3 } { + # The minimum window size is 3, so force that. + set src_size_after 3 + set asm_size_after 3 + } elseif { [expr $split_size % 2] == 0 } { + # The remaining space can be divided evenly between the two + # windows. + set src_size_after ${split_size} + set asm_size_after ${split_size} + } else { + # The space can't be divided evenly, the asm window will get + # the extra line. + set src_size_after ${split_size} + set asm_size_after [expr ${split_size} + 1] + } + + Term::command "layout src" + Term::command "winheight cmd ${cmd_size}" + Term::check_box "check for src window" 0 0 80 ${src_size_before} + + # Both windows should be of equal size, which will be their minimum. + Term::command "layout split" + Term::check_box "check for src window in split" 0 0 80 ${src_size_after} + Term::check_box "check for asm window in split" 0 [expr ${src_size_after} - 1] 80 ${asm_size_after} +} diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 8ba54a68fab..87097cb7166 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -765,6 +765,30 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) width = width_; height = height_; + /* In some situations we fix the size of the cmd window. However, + occasionally this turns out to be a mistake. This struct is used to + hold the original information about the cmd window, so we can restore + it if needed. */ + struct old_size_info + { + /* Constructor. */ + old_size_info (int index_, int min_size_, int max_size_) + : index (index_), + min_size (min_size_), + max_size (max_size_) + { /* Nothing. */ } + + /* The index in m_splits where the cmd window was found. */ + int index; + + /* The previous min/max size. */ + int min_size; + int max_size; + }; + + /* This is given a value only if we fix the size of the cmd window. */ + gdb::optional<old_size_info> old_cmd_info; + std::vector<size_info> info (m_splits.size ()); tui_debug_printf ("weights are: %s", @@ -792,6 +816,10 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) && m_splits[i].layout->get_name () != nullptr && strcmp (m_splits[i].layout->get_name (), "cmd") == 0) { + /* Save the old cmd window information, in case we need to + restore it later. */ + old_cmd_info.emplace (i, info[i].min_size, info[i].max_size); + /* If this layout has never been applied, then it means the user just changed the layout. In this situation, it's desirable to keep the size of the command window the @@ -867,22 +895,66 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) tui_debug_print_size_info (info); } + /* If we didn't find any sub-layouts that were of a non-fixed size, but + we did find the cmd window, then we can consider that a sort-of + non-fixed size sub-layout. + + The cmd window might, initially, be of a fixed size (see above), but, + we are willing to relax this constraint if required to correctly apply + this layout (see below). */ + if (last_index == -1 && old_cmd_info.has_value ()) + last_index = old_cmd_info->index; + /* Allocate any leftover size. */ - if (available_size > used_size && last_index != -1) + if (available_size != used_size && last_index != -1) { - /* Loop over all windows until all available space is used up. */ + /* Loop over all windows until the amount of used space is equal to + the amount of available space. There's an escape hatch within + the loop in case we can't find any sub-layouts to resize. */ bool found_window_that_can_grow_p = true; for (int idx = last_index; - available_size > used_size; + available_size != used_size; idx = (idx + 1) % m_splits.size ()) { - /* Once we have visited all of the windows, check that we did - manage to allocate some more space. This prevents us getting - stuck in the loop forever if we can't allocate anything - more. */ + /* Every time we get back to last_index, which is where the loop + started, we check to make sure that we did assign some space + to a window, bringing used_size closer to available_size. + + If we didn't, but the cmd window is of a fixed size, then we + can make the console window non-fixed-size, and continue + around the loop, hopefully, this will allow the layout to be + applied correctly. + + If we still make it around the loop without moving used_size + closer to available_size, then there's nothing more we can do, + and we break out of the loop. */ if (idx == last_index) { - if (!found_window_that_can_grow_p) + /* If the used_size is greater than the available_size then + this indicates that the fixed-sized sub-layouts claimed + more space than is available. This layout is not going to + work. Our only hope at this point is to make the cmd + window non-fixed-size (if possible), and hope we can + shrink this enough to fit the rest of the sub-layouts in. + + Alternatively, we've made it around the loop without + adjusting any window's size. This likely means all + windows have hit their min or max size. Again, our only + hope is to make the cmd window non-fixed-size, and hope + this fixes all our problems. */ + if (old_cmd_info.has_value () + && ((available_size < used_size) + || !found_window_that_can_grow_p)) + { + info[old_cmd_info->index].min_size = old_cmd_info->min_size; + info[old_cmd_info->index].max_size = old_cmd_info->max_size; + tui_debug_printf + ("restoring index %d (cmd) size limits, min = %d, max = %d", + old_cmd_info->index, old_cmd_info->min_size, + old_cmd_info->max_size); + old_cmd_info.reset (); + } + else if (!found_window_that_can_grow_p) break; found_window_that_can_grow_p = false; } @@ -894,6 +966,13 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) info[idx].size += 1; used_size += 1; } + else if (available_size < used_size + && info[idx].size > info[idx].min_size) + { + found_window_that_can_grow_p = true; + info[idx].size -= 1; + used_size -= 1; + } } if (debug_tui) -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (10 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-03-04 17:17 ` Tom Tromey 2022-02-06 14:12 ` [PATCHv2 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess ` (4 subsequent siblings) 16 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit allows the user to place the cmd window within horizontal tui layouts. Consider this set of steps, carried out in an 80 columns by 24 lines terminal, using current master gdb: (gdb) tui new-layout hsrc { -horizontal src 1 cmd 1 } 1 status 1 (gdb) tui layout hsrc What you end up with is a full width cmd window with the status bar beneath. Where's the src window gone? We then try: (gdb) info win Name Lines Columns Focus src 23 3 (has focus) cmd 23 80 status 1 80 (gdb) Something weird has gone on, gdb has overlapped the cmd window with the src window. If we trigger the src window to redraw is content, for example, 'list main', then we see corruption in the cmd window as the src window overwrites it. So, what's going on? The problem is some code in tui_layout_split::apply, in tui-layout.c. Within 'Step 1', there is a loop that calculates the min/max window sizes for all windows within a tui_layout_split. However, there's a special case for the cmd window. This special case is trying to have the cmd window retain its current size when a layout is re-applied, or a new layout is applied. This makes sense, consider moving from the 'src' layout to the 'asm' layout, this looks something like this (status window removed): .-------. .-------. | src | | asm | |-------| ====> |-------| | cmd | | cmd | '-------' '-------' If the user has gone to the effort of adjusting the cmd window size, then, the thinking goes, we shouldn't reset the cmd window size when switching layouts like this. The problem though, is that when we do a switch more like this: .-----------. .-----------. | src | | | | |-----------| ====> | asm | cmd | | cmd | | | | '-----------' '-----------' Now retaining the cmd window width makes no sense; the new layout has a completely different placement for the cmd window, instead of sizing by height, we're now sizing by width. The existing code doesn't understand this though, and tried to retain the full width for the cmd window. To solve this problem, I propose we introduce the idea of a layout "fingerprint". The fingerprint tries to capture, in an abstract way, where the cmd window lives within the layout. Only when two layouts have the same fingerprint will we attempt to retain the cmd window size. The fingerprint for a layout is represented as a string, the string is a series of 'V' or 'H' characters, ending with a single 'C' character. The series of 'V' and 'H' characters represent the vertical or horizontal layouts that must be passed through to find the cmd window. Here are a few examples: # This layout is equivalent to the builtin 'src' layout. # Fingerprint: VC tui new-layout example1 src 2 status 0 cmd 1 # This layout is equivalent to the builtin 'split' layout. # Fingerprint: VC tui new-layout example2 src 1 asm 1 status 0 cmd 1 # This is the same layout that was given at the top. # Fingerprint: VHC tui new-layout hsrc { -horizontal src 1 cmd 1 } 1 status 1 And so, when switching between example1 and example2, gdb knows that the cmd window is, basically, in the same sort of position within the layout, and will retain the cmd window size. In contrast, when switching to the hsrc layout, gdb understands that the position of the cmd window is different, and does not try to retain the cmd window size. --- gdb/testsuite/gdb.tui/new-layout.exp | 5 ++ gdb/tui/tui-layout.c | 69 ++++++++++++++++++++++------ gdb/tui/tui-layout.h | 47 +++++++++++++++---- gdb/tui/tui-win.c | 6 ++- 4 files changed, 102 insertions(+), 25 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index 0d49d033be5..883c7601be7 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -71,6 +71,11 @@ set layouts \ [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \ {{0 0 40 15} {39 0 41 15}} \ "$hex <main>.*21.*return 0"] \ + [list example3 "{-horizontal src 1 cmd 1} 1 status 0 asm 1" \ + {{0 0 40 11} {0 12 80 12}} \ + "21.*return 0.*$hex <main>"] \ + [list example4 "src 1 status 0 {-horizontal cmd 1 regs 1} 1" \ + {{0 0 80 11} {40 12 40 12}} ""] \ [list cmd_only "cmd 1" {} ""]] # Helper function to verify a list of boxes. diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 87097cb7166..ac03e88acbe 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -67,7 +67,7 @@ std::vector<tui_win_info *> tui_windows; /* See tui-layout.h. */ void -tui_apply_current_layout () +tui_apply_current_layout (bool preserve_cmd_win_size_p) { struct gdbarch *gdbarch; CORE_ADDR addr; @@ -77,7 +77,8 @@ tui_apply_current_layout () for (tui_win_info *win_info : tui_windows) win_info->make_visible (false); - applied_layout->apply (0, 0, tui_term_width (), tui_term_height ()); + applied_layout->apply (0, 0, tui_term_width (), tui_term_height (), + preserve_cmd_win_size_p); /* Keep the list of internal windows up-to-date. */ for (int win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++) @@ -134,9 +135,18 @@ tui_adjust_window_width (struct tui_win_info *win, int new_width) static void tui_set_layout (tui_layout_split *layout) { + std::string old_fingerprint; + if (applied_layout != nullptr) + old_fingerprint = applied_layout->layout_fingerprint (); + applied_skeleton = layout; applied_layout = layout->clone (); - tui_apply_current_layout (); + + std::string new_fingerprint = applied_layout->layout_fingerprint (); + bool preserve_command_window_size + = (TUI_CMD_WIN != nullptr && old_fingerprint == new_fingerprint); + + tui_apply_current_layout (preserve_command_window_size); } /* See tui-layout.h. */ @@ -158,7 +168,7 @@ tui_add_win_to_layout (enum tui_win_type type) const char *name = type == SRC_WIN ? SRC_NAME : DISASSEM_NAME; applied_layout->replace_window (tui_win_list[other]->name (), name); - tui_apply_current_layout (); + tui_apply_current_layout (true); } /* Find LAYOUT in the "layouts" global and return its index. */ @@ -271,7 +281,7 @@ tui_remove_some_windows () } applied_layout->remove_windows (focus->name ()); - tui_apply_current_layout (); + tui_apply_current_layout (true); } static void @@ -411,7 +421,8 @@ tui_layout_window::clone () const /* See tui-layout.h. */ void -tui_layout_window::apply (int x_, int y_, int width_, int height_) +tui_layout_window::apply (int x_, int y_, int width_, int height_, + bool preserve_cmd_win_size_p) { x = x_; y = y_; @@ -510,6 +521,17 @@ tui_layout_window::specification (ui_file *output, int depth) /* See tui-layout.h. */ +std::string +tui_layout_window::layout_fingerprint () const +{ + if (strcmp (get_name (), "cmd") == 0) + return "C"; + else + return ""; +} + +/* See tui-layout.h. */ + void tui_layout_split::add_split (std::unique_ptr<tui_layout_split> &&layout, int weight) @@ -746,8 +768,11 @@ tui_layout_split::set_size (const char *name, int new_size) } else { - /* Simply re-apply the updated layout. */ - apply (x, y, width, height); + /* Simply re-apply the updated layout. We pass false here so that + the cmd window can be resized. However, we should have already + resized everything above to be "just right", so the apply call + here should not end up changing the sizes at all. */ + apply (x, y, width, height, false); } return HANDLED; @@ -756,7 +781,8 @@ tui_layout_split::set_size (const char *name, int new_size) /* See tui-layout.h. */ void -tui_layout_split::apply (int x_, int y_, int width_, int height_) +tui_layout_split::apply (int x_, int y_, int width_, int height_, + bool preserve_cmd_win_size_p) { TUI_SCOPED_DEBUG_ENTER_EXIT; @@ -811,7 +837,7 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) m_splits[i].layout->get_sizes (m_vertical, &info[i].min_size, &info[i].max_size); - if (!m_applied + if (preserve_cmd_win_size_p && cmd_win_already_exists && m_splits[i].layout->get_name () != nullptr && strcmp (m_splits[i].layout->get_name (), "cmd") == 0) @@ -998,13 +1024,13 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) else if (info[i].share_box) --size_accum; if (m_vertical) - m_splits[i].layout->apply (x, y + size_accum, width, info[i].size); + m_splits[i].layout->apply (x, y + size_accum, width, info[i].size, + preserve_cmd_win_size_p); else - m_splits[i].layout->apply (x + size_accum, y, info[i].size, height); + m_splits[i].layout->apply (x + size_accum, y, info[i].size, height, + preserve_cmd_win_size_p); size_accum += info[i].size; } - - m_applied = true; } /* See tui-layout.h. */ @@ -1065,6 +1091,21 @@ tui_layout_split::specification (ui_file *output, int depth) fputs_unfiltered ("}", output); } +/* See tui-layout.h. */ + +std::string +tui_layout_split::layout_fingerprint () const +{ + for (auto &item : m_splits) + { + std::string fp = item.layout->layout_fingerprint (); + if (!fp.empty ()) + return std::string (m_vertical ? "V" : "H") + fp; + } + + return ""; +} + /* Destroy the layout associated with SELF. */ static void diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index e160eaa2256..32f9dd078ee 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -55,8 +55,12 @@ class tui_layout_base "skeleton" layout. */ virtual std::unique_ptr<tui_layout_base> clone () const = 0; - /* Change the size and location of this layout. */ - virtual void apply (int x, int y, int width, int height) = 0; + /* Change the size and location of this layout. When + PRESERVE_CMD_WIN_SIZE_P is true the current size of the TUI_CMD_WIN + is preserved, otherwise, the TUI_CMD_WIN will resize just like any + other window. */ + virtual void apply (int x, int y, int width, int height, + bool preserve_cmd_win_size_p) = 0; /* Return the minimum and maximum height or width of this layout. HEIGHT is true to fetch height, false to fetch width. */ @@ -101,6 +105,26 @@ class tui_layout_base depth of this layout in the hierarchy (zero-based). */ virtual void specification (ui_file *output, int depth) = 0; + /* Return a FINGERPRINT string containing an abstract representation of + the location of the cmd window in this layout. + + When called on a complete, top-level layout, the fingerprint will be a + non-empty string made of 'V' and 'H' characters, followed by a single + 'C' character. Each 'V' and 'H' represents a vertical or horizontal + layout that must be passed through in order to find the cmd + window. + + Of course, layouts are built recursively, so, when called on a partial + layout, if this object represents a single window, then either the + empty string is returned (for non-cmd windows), or a string + containing a single 'C' is returned. + + For object representing layouts, if the layout contains the cmd + window then we will get back a valid fingerprint string (contains 'V' + and 'H', ends with 'C'), or, if this layout doesn't contain the cmd + window, an empty string is returned. */ + virtual std::string layout_fingerprint () const = 0; + /* Add all windows to the WINDOWS vector. */ virtual void get_windows (std::vector<tui_win_info *> *windows) = 0; @@ -130,7 +154,8 @@ class tui_layout_window : public tui_layout_base std::unique_ptr<tui_layout_base> clone () const override; - void apply (int x, int y, int width, int height) override; + void apply (int x, int y, int width, int height, + bool preserve_cmd_win_size_p) override; const char *get_name () const override { @@ -163,6 +188,8 @@ class tui_layout_window : public tui_layout_base void specification (ui_file *output, int depth) override; + std::string layout_fingerprint () const override; + /* See tui_layout_base::get_windows. */ void get_windows (std::vector<tui_win_info *> *windows) override { @@ -209,7 +236,8 @@ class tui_layout_split : public tui_layout_base std::unique_ptr<tui_layout_base> clone () const override; - void apply (int x, int y, int width, int height) override; + void apply (int x, int y, int width, int height, + bool preserve_cmd_win_size_p) override; tui_adjust_result set_height (const char *name, int new_height) override { @@ -235,6 +263,8 @@ class tui_layout_split : public tui_layout_base void specification (ui_file *output, int depth) override; + std::string layout_fingerprint () const override; + /* See tui_layout_base::get_windows. */ void get_windows (std::vector<tui_win_info *> *windows) override { @@ -371,9 +401,6 @@ class tui_layout_split : public tui_layout_base /* True if the windows in this split are arranged vertically. */ bool m_vertical; - - /* True if this layout has already been applied at least once. */ - bool m_applied = false; }; /* Add the specified window to the layout in a logical way. This @@ -396,8 +423,10 @@ extern void tui_regs_layout (); some other window is chosen to remain. */ extern void tui_remove_some_windows (); -/* Apply the current layout. */ -extern void tui_apply_current_layout (); +/* Apply the current layout. When PRESERVE_CMD_WIN_SIZE_P is true the + current size of the TUI_CMD_WIN is preserved, otherwise, the TUI_CMD_WIN + will resize just like any other window. */ +extern void tui_apply_current_layout (bool); /* Adjust the window height of WIN to NEW_HEIGHT. */ extern void tui_adjust_window_height (struct tui_win_info *win, diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index 953af640c93..d7fd8411a66 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -511,8 +511,10 @@ tui_resize_all (void) AIX 5.3 does not define clear. */ erase (); clearok (curscr, TRUE); - tui_apply_current_layout (); - /* Turn keypad back on. */ + /* Apply the current layout. The 'false' here allows the command + window to resize proportionately with containing terminal, rather + than maintaining a fixed size. */ + tui_apply_current_layout (false); /* Turn keypad back on. */ keypad (TUI_CMD_WIN->handle.get (), TRUE); } } -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout 2022-02-06 14:12 ` [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess @ 2022-03-04 17:17 ` Tom Tromey 2022-03-07 20:05 ` Andrew Burgess 0 siblings, 1 reply; 74+ messages in thread From: Tom Tromey @ 2022-03-04 17:17 UTC (permalink / raw) To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess >>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes: Andrew> This commit allows the user to place the cmd window within horizontal Andrew> tui layouts. Do these really work? I forget exactly why, but I vaguely recall that there is some reason the command window doesn't interact nicely with arbitrary layouts. It might be because the command window is unboxed, so the rendering looks strange. Or maybe it affects the pager somehow? Anyway, I'm all for it working if possible. Tom ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout 2022-03-04 17:17 ` Tom Tromey @ 2022-03-07 20:05 ` Andrew Burgess 2022-03-07 21:24 ` Tom Tromey 0 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 20:05 UTC (permalink / raw) To: Tom Tromey, Andrew Burgess via Gdb-patches Tom Tromey <tom@tromey.com> writes: >>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes: > > Andrew> This commit allows the user to place the cmd window within horizontal > Andrew> tui layouts. > > Do these really work? I forget exactly why, but I vaguely recall that > there is some reason the command window doesn't interact nicely with > arbitrary layouts. > > It might be because the command window is unboxed, so the rendering > looks strange. Or maybe it affects the pager somehow? I've not noticed anything particularly strange so far. At least, nothing so strange that I think we should not go ahead with this change. I have seen a couple of weird page issues when I created a particularly narrow CMD window - it almost seemed like the page was confused about how many lines it had drawn. But for the most part everything seemed OK. My preference would be to get this in (after I've addressed the other feedback), then if we see problems we can start to address issues. I don't think that the user experience is so bad that we should go ahead with this. Let me know if you're happy with this approach. Thanks, Andrew ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout 2022-03-07 20:05 ` Andrew Burgess @ 2022-03-07 21:24 ` Tom Tromey 0 siblings, 0 replies; 74+ messages in thread From: Tom Tromey @ 2022-03-07 21:24 UTC (permalink / raw) To: Andrew Burgess; +Cc: Tom Tromey, Andrew Burgess via Gdb-patches Andrew> But for the most part everything seemed OK. Andrew> My preference would be to get this in (after I've addressed the other Andrew> feedback), then if we see problems we can start to address issues. I Andrew> don't think that the user experience is so bad that we should go ahead Andrew> with this. Andrew> Let me know if you're happy with this approach. Yeah, it's fine by me. Tom ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (11 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess ` (3 subsequent siblings) 16 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit just adds an extra check of the src window size prior to sending all the commands to gdb. We also set the cmd window height to its existing height, this (obviously) shouldn't change the window layout, which we check. My main motivation was adding the initial window layout check, the winheight and recheck are just extras. All of these test pass both before and after this commit. --- gdb/testsuite/gdb.tui/scroll.exp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gdb/testsuite/gdb.tui/scroll.exp b/gdb/testsuite/gdb.tui/scroll.exp index 4eaee0c14ee..c23cd2b9abf 100644 --- a/gdb/testsuite/gdb.tui/scroll.exp +++ b/gdb/testsuite/gdb.tui/scroll.exp @@ -55,6 +55,10 @@ Term::check_region_contents "check cmd window" 0 16 80 8 \ Term::command "tui new-layout flip cmd 1 src 1" Term::command "layout flip" +Term::check_box "src window" 0 8 80 16 +Term::command "winheight cmd 8" +Term::check_box "src window after resize" 0 8 80 16 + for {set i 10} {$i < 20} {incr i 1} { Term::command "p $i" } -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (12 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-03-04 17:20 ` Tom Tromey 2022-02-06 14:12 ` [PATCHv2 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess ` (2 subsequent siblings) 16 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit removes some arbitrary adjustments made in tui_cmd_window::max_height, tui_win_info::max_height, and tui_win_info::max_width. These member functions all subtract some constant from the theoretical maximum height or width. I've looked back through the history a little and can see no real reason why these adjustments should be needed, with these adjustments removed all the existing tui tests still pass. However, retaining these restrictions causes some bugs, consider: (gdb) tui new-layout hsrc {-horizontal src 1 cmd 1} 1 When this layout is selected with current master, gdb will leave a 4 line gap at the bottom of the terminal. The problem is that the maximum height is restricted, for the cmd window, to 4 less than the terminal height. By removing this restriction gdb is able to size the windows to the complete terminal height, and the layout is done correctly. This 4 line restriction is also what prevents this layout from working correctly: (gdb) tui new-layout conly cmd 1 Previously, this layout would present a cmd window only, but there would be a 4 line gap at the bottom of the terminal. This issue was mentioned in an earlier commit in this series (when a different bug was fixed), but with this commit, the above layout now correctly fills the terminal. The associated test is updated. After removing the adjustment in tui_cmd_window::max_height, the implementation is now the same as the implementation in the parent class tui_win_info, so I've completely removed the max_height call from tui_cmd_window. --- gdb/testsuite/gdb.tui/new-layout.exp | 4 +++- gdb/tui/tui-command.c | 6 ------ gdb/tui/tui-command.h | 2 -- gdb/tui/tui-win.c | 4 ++-- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index 883c7601be7..e662b1f0b18 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -76,6 +76,8 @@ set layouts \ "21.*return 0.*$hex <main>"] \ [list example4 "src 1 status 0 {-horizontal cmd 1 regs 1} 1" \ {{0 0 80 11} {40 12 40 12}} ""] \ + [list example5 "{-horizontal src 1 cmd 1} 1 status 0" \ + {{0 0 40 23}} ""] \ [list cmd_only "cmd 1" {} ""]] # Helper function to verify a list of boxes. @@ -136,7 +138,7 @@ foreach_with_prefix layout $layouts { Term::check_region_contents "info win output" \ 0 0 80 24 [multi_line "info win\\s+" \ "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \ - "cmd\\s+20\\s+80\\s+\\(has focus\\)\\s+" \ + "cmd\\s+24\\s+80\\s+\\(has focus\\)\\s+" \ "$gdb_prompt\\s+"] } } diff --git a/gdb/tui/tui-command.c b/gdb/tui/tui-command.c index fa8af970b0a..0f6c395f567 100644 --- a/gdb/tui/tui-command.c +++ b/gdb/tui/tui-command.c @@ -31,12 +31,6 @@ /* See tui-command.h. */ -int -tui_cmd_window::max_height () const -{ - return tui_term_height () - 4; -} - void tui_cmd_window::resize (int height_, int width_, int origin_x, int origin_y) { diff --git a/gdb/tui/tui-command.h b/gdb/tui/tui-command.h index 06cc24f6faf..6c354361d1d 100644 --- a/gdb/tui/tui-command.h +++ b/gdb/tui/tui-command.h @@ -31,8 +31,6 @@ struct tui_cmd_window : public tui_win_info DISABLE_COPY_AND_ASSIGN (tui_cmd_window); - int max_height () const override; - void refresh_window () override { } diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index d7fd8411a66..6ff65052396 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -986,7 +986,7 @@ tui_set_win_width_command (const char *arg, int from_tty) int tui_win_info::max_height () const { - return tui_term_height () - 2; + return tui_term_height (); } /* See tui-data.h. */ @@ -994,7 +994,7 @@ tui_win_info::max_height () const int tui_win_info::max_width () const { - return tui_term_width () - 2; + return tui_term_width (); } static void -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width 2022-02-06 14:12 ` [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess @ 2022-03-04 17:20 ` Tom Tromey 2022-03-07 20:08 ` Andrew Burgess 0 siblings, 1 reply; 74+ messages in thread From: Tom Tromey @ 2022-03-04 17:20 UTC (permalink / raw) To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess >>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes: Andrew> int Andrew> tui_win_info::max_height () const Andrew> { Andrew> - return tui_term_height () - 2; Andrew> + return tui_term_height (); I suspect this kind of thing is to ensure there's room for the box. It's also possible this is just ancient code. Despite the big TUI refactorings, there's still some leftover weird stuff in there. Tom ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width 2022-03-04 17:20 ` Tom Tromey @ 2022-03-07 20:08 ` Andrew Burgess 0 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 20:08 UTC (permalink / raw) To: Tom Tromey, Andrew Burgess via Gdb-patches Tom Tromey <tom@tromey.com> writes: >>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes: > > Andrew> int > Andrew> tui_win_info::max_height () const > Andrew> { > Andrew> - return tui_term_height () - 2; > Andrew> + return tui_term_height (); > > I suspect this kind of thing is to ensure there's room for the box. > It's also possible this is just ancient code. Despite the big TUI > refactorings, there's still some leftover weird stuff in there. Maybe it was once, but I assume that if it was still needed then I'd see issues once it was removed. And I don't. As far as I understand things, the layout algorithm takes tui_term_height and assigns that space out to the container windows. The space allocated to a window is expected to include the windows border. So limiting the max window size like this just means we can never have a single window fill the terminal. I'll do more testing while I'm addressing the other feedback issues, and if you have any suggestions for things to try that might reveal a bug related to this change, then I'm happy to give it a go. But otherwise, as far as I can tell, the above change is fine. Thanks, Andrew ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv2 15/15] gdb/tui: fair split of delta after a resize 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (13 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess @ 2022-02-06 14:12 ` Andrew Burgess 2022-03-04 17:22 ` Tom Tromey 2022-02-21 17:29 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess 16 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-02-06 14:12 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess Currently, in master gdb, when a tui window is changed in size, the screen delta is mostly just added to the next available window. We do take care to respect the min/max size, but in most cases, these limits are just "the terminal size", and so, we end up placing the whole delta on the next window. Consider these steps in an 80 column, 24 line terminal: (gdb) tui enable (gdb) layout src (gdb) layout split (gdb) info win Name Lines Columns Focus src 8 80 (has focus) asm 8 80 status 1 80 cmd 8 80 (gdb) winheight cmd +2 (gdb) info win Name Lines Columns Focus src 6 80 (has focus) asm 8 80 status 1 80 cmd 10 80 Notice that initially, the windows were balanced, 8 lines each for the major windows. Then, when the cmd window was adjusted, the extra two lines were given to the asm window. I think it would be nicer if the delta was spread more evenly over the available windows. In the example above, after the adjustment the layout now looks like: (gdb) info win Name Lines Columns Focus src 7 80 (has focus) asm 7 80 status 1 80 cmd 10 80 This is achieved within tui_layout_split::set_size, by just handing out the delta in increments of 1 to each window (except for the window the user adjusted), until there's no more delta left. Of course, we continue to respect the min/max window sizes. --- gdb/testsuite/gdb.tui/winheight.exp | 31 +++++++++++++++++++++++++++++ gdb/tui/tui-layout.c | 30 +++++++++++++++++++--------- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/gdb/testsuite/gdb.tui/winheight.exp b/gdb/testsuite/gdb.tui/winheight.exp index b541c21b825..8296dd79513 100644 --- a/gdb/testsuite/gdb.tui/winheight.exp +++ b/gdb/testsuite/gdb.tui/winheight.exp @@ -43,11 +43,42 @@ Term::check_box "smaller source box again" 0 0 80 10 Term::command "winheight src +5" Term::check_box "larger source box again" 0 0 80 15 +# Check that attempting a window to be too large gives an error. +Term::command "winheight src 100" +Term::check_box "source box has not changed" 0 0 80 15 +Term::check_region_contents "check error message about src size 100" 0 16 80 8 \ + [multi_line "$gdb_prompt winheight src 100\\s+" \ + "warning: Invalid window height specified\\s+" \ + "$gdb_prompt"] + +# Check that incrementing to a size that is "too big" will trigger an +# error, and that the window doesn't resize. +Term::command "winheight src 20" +Term::check_box "source box is at its max size" 0 0 80 20 +Term::command "winheight src +1" +Term::check_box "source box is still at its max size" 0 0 80 20 +Term::check_region_contents "check error message about src +1" 0 21 80 3 \ + [multi_line "$gdb_prompt winheight src \\+1\\s+" \ + "warning: Invalid window height specified\\s+" \ + "$gdb_prompt"] + +# Reset the cmd window to a sane size. +Term::command "winheight cmd 8" + +Term::command "layout regs" +Term::check_box "register window" 0 0 80 8 +Term::check_box "source window" 0 7 80 8 + +Term::command "winheight cmd 10" +Term::check_box "register window after resize" 0 0 80 7 +Term::check_box "source window after resize" 0 6 80 7 + # At one point we had a bug where adjusting the winheight would result # in GDB keeping hold of duplicate window pointers, which it might # then try to delete when the layout was changed. Running this test # under valgrind would expose that bug. Term::command "layout asm" +Term::command "winheight cmd 8" Term::check_box "check for asm window" 0 0 80 15 diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index ac03e88acbe..ef98aaeef9d 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -727,9 +727,17 @@ tui_layout_split::set_size (const char *name, int new_size) /* Distribute the "delta" over the next window; but if the next window cannot hold it all, keep going until we either find a window that does, or until we loop all the way around. */ - for (int i = 0; delta != 0 && i < m_splits.size () - 1; ++i) + bool found_window_that_can_grow_p = true; + for (int i = 0; delta != 0; i = (i + 1) % m_splits.size ()) { int index = (found_index + 1 + i) % m_splits.size (); + if (index == found_index) + { + if (!found_window_that_can_grow_p) + break; + found_window_that_can_grow_p = false; + continue; + } int new_min, new_max; m_splits[index].layout->get_sizes (m_vertical, &new_min, &new_max); @@ -738,19 +746,23 @@ tui_layout_split::set_size (const char *name, int new_size) { /* The primary window grew, so we are trying to shrink other windows. */ - int available = m_splits[index].weight - new_min; - int shrink_by = std::min (available, -delta); - m_splits[index].weight -= shrink_by; - delta += shrink_by; + if (m_splits[index].weight > new_min) + { + m_splits[index].weight -= 1; + delta += 1; + found_window_that_can_grow_p = true; + } } else { /* The primary window shrank, so we are trying to grow other windows. */ - int available = new_max - m_splits[index].weight; - int grow_by = std::min (available, delta); - m_splits[index].weight += grow_by; - delta -= grow_by; + if (m_splits[index].weight < new_max) + { + m_splits[index].weight += 1; + delta -= 1; + found_window_that_can_grow_p = true; + } } tui_debug_printf ("index = %d, weight now: %d", -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 15/15] gdb/tui: fair split of delta after a resize 2022-02-06 14:12 ` [PATCHv2 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess @ 2022-03-04 17:22 ` Tom Tromey 2022-03-07 22:07 ` Andrew Burgess 0 siblings, 1 reply; 74+ messages in thread From: Tom Tromey @ 2022-03-04 17:22 UTC (permalink / raw) To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess >>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes: Andrew> Currently, in master gdb, when a tui window is changed in size, the Andrew> screen delta is mostly just added to the next available window. We Andrew> do take care to respect the min/max size, but in most cases, these Andrew> limits are just "the terminal size", and so, we end up placing the Andrew> whole delta on the next window. This seems like a change that corresponds to the same change in the patch to change how layouts are applied. That is, the resize-one-window code and the layout-from-scratch code ought to agree algorithmically. So maybe this should have been merged into that one -- though I'm not really too picky about that kind of thing. Tom ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 15/15] gdb/tui: fair split of delta after a resize 2022-03-04 17:22 ` Tom Tromey @ 2022-03-07 22:07 ` Andrew Burgess 2022-03-07 23:42 ` Tom Tromey 0 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:07 UTC (permalink / raw) To: Tom Tromey, Andrew Burgess via Gdb-patches Tom Tromey <tom@tromey.com> writes: >>>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes: > > Andrew> Currently, in master gdb, when a tui window is changed in size, the > Andrew> screen delta is mostly just added to the next available window. We > Andrew> do take care to respect the min/max size, but in most cases, these > Andrew> limits are just "the terminal size", and so, we end up placing the > Andrew> whole delta on the next window. > > This seems like a change that corresponds to the same change in the > patch to change how layouts are applied. That is, the resize-one-window > code and the layout-from-scratch code ought to agree algorithmically. > So maybe this should have been merged into that one -- though I'm not > really too picky about that kind of thing. Originally, I did try to do this, but in the end I decided not too as the amount of change seemed much bigger than needed. The problem is that we end up needing to add a mechanism to "lock" a window size - we have a layout with windows A, B, and C. The user sets the size of window B. With the code in my patch we set the size of B as the user requested, and then resize A and C around B. If we try to use apply, then, after changing the size of B, we need some way to tell ::apply that it must not change the size of B again. This is totally doable, at one point I had a version of this patch that did just this, but it was a big code change. I'd much rather push this smaller change, which allows me to get additional tests into place, then, if we want, we can try to refactor things later, and merge the two code paths together. Would this be OK? Thanks, Andrew ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 15/15] gdb/tui: fair split of delta after a resize 2022-03-07 22:07 ` Andrew Burgess @ 2022-03-07 23:42 ` Tom Tromey 0 siblings, 0 replies; 74+ messages in thread From: Tom Tromey @ 2022-03-07 23:42 UTC (permalink / raw) To: Andrew Burgess; +Cc: Tom Tromey, Andrew Burgess via Gdb-patches Andrew> Originally, I did try to do this, but in the end I decided not too as Andrew> the amount of change seemed much bigger than needed. Yeah, makes sense. Andrew> I'd much rather push this smaller change, which allows me to get Andrew> additional tests into place, then, if we want, we can try to refactor Andrew> things later, and merge the two code paths together. Andrew> Would this be OK? We don't even really have to merge them. Anyway it's all fine with me, I appreciate you looking into this and the results seem good. Tom ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (14 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess @ 2022-02-21 17:29 ` Andrew Burgess 2022-03-02 17:59 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess 16 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-02-21 17:29 UTC (permalink / raw) To: gdb-patches Ping! Thanks, Andrew Andrew Burgess <aburgess@redhat.com> writes: > I pushed the first two patches from the v1 series, but the rest of > that original series does need reviewing - those paches are included > in v2 as patches 1 to 5. > > The remaining 10 patches in the v2 series mostly relate to changing > how window resizing, and window layout occurs. > > The docs content in patches 1 and 5 of the v2 series is unchanged from > v1, and was already reviewed, so no new docs review is required there. > > There is some new docs content in patch 6, but its pretty minor; a > docs review is always welcome though. > > I'm hoping most of the changes in this series will be pretty > non-controversial, the only patch which I think might be more of a > personal taste issue is the very last one (left last for that reason). > I'd suggest selecting the split layout, and then playing with window > resizing to get a feel for the new behaviour. Feedback welcome. > > Thanks, > Andrew > > --- > > Andrew Burgess (15): > gdb: move some commands into the tui namespace > gdb/tui: rename tui_layout_base::adjust_size to ::set_height > gdb/tui: rename tui_layout_split:set_weights_from_heights > gdb/testing/tui: add new functionality to tuiterm.exp > gdb/tui: add new 'tui window width' command and 'winwidth' alias > gdb/tui: add a tui debugging flag > gdb/tui: add left_boxed_p and right_boxed_p member functions > gdb/tui/testsuite: refactor new-layout.exp test > gdb/tui: avoid fp exception when applying layouts > gdb/tui: fairer distribution of excess space during apply > gdb/tui: allow cmd window to change size in tui_layout_split::apply > gdb/tui: support placing the cmd window into a horizontal layout > gdb/testsuite: some additional tests in gdb.tui/scroll.exp > gdb/tui: relax restrictions on window max height and width > gdb/tui: fair split of delta after a resize > > gdb/NEWS | 25 ++ > gdb/doc/gdb.texinfo | 41 ++- > gdb/testsuite/gdb.tui/basic.exp | 4 +- > gdb/testsuite/gdb.tui/empty.exp | 14 +- > gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++-- > gdb/testsuite/gdb.tui/regs.exp | 4 +- > gdb/testsuite/gdb.tui/scroll.exp | 4 + > gdb/testsuite/gdb.tui/winheight.exp | 77 +++++ > gdb/testsuite/gdb.tui/winwidth.exp | 63 ++++ > gdb/testsuite/lib/tuiterm.exp | 82 +++++- > gdb/tui/tui-command.c | 6 - > gdb/tui/tui-command.h | 2 - > gdb/tui/tui-layout.c | 419 +++++++++++++++++++++++---- > gdb/tui/tui-layout.h | 201 ++++++++++++- > gdb/tui/tui-win.c | 149 ++++++++-- > gdb/tui/tui.c | 26 ++ > gdb/tui/tui.h | 14 + > 17 files changed, 1089 insertions(+), 142 deletions(-) > create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp > > -- > 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes 2022-02-21 17:29 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess @ 2022-03-02 17:59 ` Andrew Burgess 0 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-02 17:59 UTC (permalink / raw) To: gdb-patches Ping! Thanks, Andrew Andrew Burgess <aburgess@redhat.com> writes: > Ping! > > Thanks, > Andrew > > > Andrew Burgess <aburgess@redhat.com> writes: > >> I pushed the first two patches from the v1 series, but the rest of >> that original series does need reviewing - those paches are included >> in v2 as patches 1 to 5. >> >> The remaining 10 patches in the v2 series mostly relate to changing >> how window resizing, and window layout occurs. >> >> The docs content in patches 1 and 5 of the v2 series is unchanged from >> v1, and was already reviewed, so no new docs review is required there. >> >> There is some new docs content in patch 6, but its pretty minor; a >> docs review is always welcome though. >> >> I'm hoping most of the changes in this series will be pretty >> non-controversial, the only patch which I think might be more of a >> personal taste issue is the very last one (left last for that reason). >> I'd suggest selecting the split layout, and then playing with window >> resizing to get a feel for the new behaviour. Feedback welcome. >> >> Thanks, >> Andrew >> >> --- >> >> Andrew Burgess (15): >> gdb: move some commands into the tui namespace >> gdb/tui: rename tui_layout_base::adjust_size to ::set_height >> gdb/tui: rename tui_layout_split:set_weights_from_heights >> gdb/testing/tui: add new functionality to tuiterm.exp >> gdb/tui: add new 'tui window width' command and 'winwidth' alias >> gdb/tui: add a tui debugging flag >> gdb/tui: add left_boxed_p and right_boxed_p member functions >> gdb/tui/testsuite: refactor new-layout.exp test >> gdb/tui: avoid fp exception when applying layouts >> gdb/tui: fairer distribution of excess space during apply >> gdb/tui: allow cmd window to change size in tui_layout_split::apply >> gdb/tui: support placing the cmd window into a horizontal layout >> gdb/testsuite: some additional tests in gdb.tui/scroll.exp >> gdb/tui: relax restrictions on window max height and width >> gdb/tui: fair split of delta after a resize >> >> gdb/NEWS | 25 ++ >> gdb/doc/gdb.texinfo | 41 ++- >> gdb/testsuite/gdb.tui/basic.exp | 4 +- >> gdb/testsuite/gdb.tui/empty.exp | 14 +- >> gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++-- >> gdb/testsuite/gdb.tui/regs.exp | 4 +- >> gdb/testsuite/gdb.tui/scroll.exp | 4 + >> gdb/testsuite/gdb.tui/winheight.exp | 77 +++++ >> gdb/testsuite/gdb.tui/winwidth.exp | 63 ++++ >> gdb/testsuite/lib/tuiterm.exp | 82 +++++- >> gdb/tui/tui-command.c | 6 - >> gdb/tui/tui-command.h | 2 - >> gdb/tui/tui-layout.c | 419 +++++++++++++++++++++++---- >> gdb/tui/tui-layout.h | 201 ++++++++++++- >> gdb/tui/tui-win.c | 149 ++++++++-- >> gdb/tui/tui.c | 26 ++ >> gdb/tui/tui.h | 14 + >> 17 files changed, 1089 insertions(+), 142 deletions(-) >> create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp >> >> -- >> 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess ` (15 preceding siblings ...) 2022-02-21 17:29 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 01/15] gdb: move some commands into the tui namespace Andrew Burgess ` (15 more replies) 16 siblings, 16 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess Since v2: - Rebased onto current upstream/master, - Patch #5 - Rewritten to not use templates! - Patch #6 - Added a bug in bugzilla, and referenced this from the commit message, - Patch #7 - Renamed the existing methods rather than adding 2 new methods, - Patch #10 - Updated the comment Tom identified as being out of date, - Patch #15 - Have updated a comment that I spotted was out of date. Thanks, Andrew --- Andrew Burgess (15): gdb: move some commands into the tui namespace gdb/tui: rename tui_layout_base::adjust_size to ::set_height gdb/tui: rename tui_layout_split:set_weights_from_heights gdb/testing/tui: add new functionality to tuiterm.exp gdb/tui: add new 'tui window width' command and 'winwidth' alias gdb/tui: add a tui debugging flag gdb/tui: add left_boxed_p and right_boxed_p member functions gdb/tui/testsuite: refactor new-layout.exp test gdb/tui: avoid fp exception when applying layouts gdb/tui: fairer distribution of excess space during apply gdb/tui: allow cmd window to change size in tui_layout_split::apply gdb/tui: support placing the cmd window into a horizontal layout gdb/testsuite: some additional tests in gdb.tui/scroll.exp gdb/tui: relax restrictions on window max height and width gdb/tui: fair split of delta after a resize gdb/NEWS | 25 ++ gdb/doc/gdb.texinfo | 51 +++- gdb/testsuite/gdb.tui/basic.exp | 4 +- gdb/testsuite/gdb.tui/empty.exp | 14 +- gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++-- gdb/testsuite/gdb.tui/regs.exp | 4 +- gdb/testsuite/gdb.tui/scroll.exp | 4 + gdb/testsuite/gdb.tui/winheight.exp | 77 +++++ gdb/testsuite/gdb.tui/winwidth.exp | 63 +++++ gdb/testsuite/lib/tuiterm.exp | 82 +++++- gdb/tui/tui-command.c | 6 - gdb/tui/tui-command.h | 2 - gdb/tui/tui-layout.c | 406 ++++++++++++++++++++++----- gdb/tui/tui-layout.h | 135 +++++++-- gdb/tui/tui-win.c | 118 ++++++-- gdb/tui/tui.c | 26 ++ gdb/tui/tui.h | 14 + 17 files changed, 971 insertions(+), 160 deletions(-) create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 01/15] gdb: move some commands into the tui namespace 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess ` (14 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess There are a lot of tui related commands that live in the top-level command name space, e.g. layout, focus, refresh, winheight. Having them at the top level means less typing for the user, which is good, but, I think, makes command discovery harder. In this commit, I propose moving all of the above mentioned commands into the tui namespace, so 'layout' becomes 'tui layout', etc. But I will then add aliases so that the old commands will still work, e.g. I'll make 'layout' an alias for 'tui layout'. The benefit I see in this work is that tui related commands can be more easily discovered by typing 'tui ' and then tab-completing. Also the "official" command is now a tui-sub-command, this is visible in, for example, the help output, e.g.: (gdb) help layout tui layout, layout Change the layout of windows. Usage: tui layout prev | next | LAYOUT-NAME List of tui layout subcommands: tui layout asm -- Apply the "asm" layout. tui layout next -- Apply the next TUI layout. tui layout prev -- Apply the previous TUI layout. tui layout regs -- Apply the TUI register layout. tui layout split -- Apply the "split" layout. tui layout src -- Apply the "src" layout. Which I think is a good thing, it makes it clearer that this is a tui command. I've added a NEWS entry and updated the docs to mention the new and old command names, with the new name being mentioned first. --- gdb/NEWS | 15 +++++++++++++++ gdb/doc/gdb.texinfo | 18 +++++++++++++----- gdb/tui/tui-layout.c | 16 +++++++++++++--- gdb/tui/tui-win.c | 40 ++++++++++++++++++++++++++++++++-------- 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index cf1e084fed6..3c3e0bbb2fb 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -119,6 +119,14 @@ show ada source-charset values for this follow the values that can be passed to the GNAT compiler via the '-gnati' option. The default is ISO-8859-1. +tui layout +tui focus +tui refresh +tui window height + These are the new names for the old 'layout', 'focus', 'refresh', + and 'winheight' tui commands respectively. The old names still + exist as aliases to these new commands. + * Changed commands maint packet @@ -144,6 +152,13 @@ info win This command now includes information about the width of the tui windows in its output. +layout +focus +refresh +winheight + These commands are now aliases for the 'tui layout', 'tui focus', + 'tui refresh', and 'tui window height' commands respectively. + * GDB's Ada parser now supports an extension for specifying the exact byte contents of a floating-point literal. This can be useful for setting floating-point registers to a precise value without loss of diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 132b94c6487..fd4c110569e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -29006,8 +29006,10 @@ width of the terminal. Because they have weight 2, the source and assembly windows will be twice the height of the command window. -@item layout @var{name} +@kindex tui layout @kindex layout +@item tui layout @var{name} +@itemx layout @var{name} Changes which TUI windows are displayed. The @var{name} parameter controls which layout is shown. It can be either one of the built-in layout names, or the name of a layout defined by the user using @@ -29037,8 +29039,9 @@ register, assembler, and command windows. @end table -@item focus @var{name} @kindex focus +@item tui focus @var{name} +@itemx focus @var{name} Changes which TUI window is currently active for scrolling. The @var{name} parameter can be any of the following: @@ -29062,8 +29065,10 @@ Make the command window active for scrolling. @end table -@item refresh +@kindex tui refresh @kindex refresh +@item tui refresh +@itemx refresh Refresh the screen. This is similar to typing @kbd{C-L}. @item tui reg @var{group} @@ -29099,9 +29104,12 @@ @kindex update Update the source window and the current execution point. -@item winheight @var{name} +@var{count} -@itemx winheight @var{name} -@var{count} +@kindex tui window height @kindex winheight +@item tui window height @var{name} +@var{count} +@itemx tui window height @var{name} -@var{count} +@itemx winheight @var{name} +@var{count} +@itemx winheight @var{name} -@var{count} Change the height of the window @var{name} by @var{count} lines. Positive counts increase the height, while negative counts decrease it. The @var{name} parameter can be the name of any currently visible diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index cef9190c3e1..f8388e3fca5 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -839,6 +839,14 @@ destroy_layout (struct cmd_list_element *self, void *context) static struct cmd_list_element *layout_list; +/* Called to implement 'tui layout'. */ + +static void +tui_layout_command (const char *args, int from_tty) +{ + help_list (layout_list, "tui layout ", all_commands, gdb_stdout); +} + /* Add a "layout" command with name NAME that switches to LAYOUT. */ static struct cmd_list_element * @@ -1017,10 +1025,12 @@ void _initialize_tui_layout (); void _initialize_tui_layout () { - add_basic_prefix_cmd ("layout", class_tui, _("\ + struct cmd_list_element *layout_cmd + = add_prefix_cmd ("layout", class_tui, tui_layout_command, _("\ Change the layout of windows.\n\ -Usage: layout prev | next | LAYOUT-NAME"), - &layout_list, 0, &cmdlist); +Usage: tui layout prev | next | LAYOUT-NAME"), + &layout_list, 0, tui_get_cmd_list ()); + add_com_alias ("layout", layout_cmd, class_tui, 0); add_cmd ("next", class_tui, tui_next_layout_command, _("Apply the next TUI layout."), diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index fd6ca59a728..ba6aca3d078 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -977,6 +977,18 @@ parse_scrolling_args (const char *arg, } } +/* The list of 'tui window' sub-commands. */ + +static cmd_list_element *tui_window_cmds = nullptr; + +/* Called to implement 'tui window'. */ + +static void +tui_window_command (const char *args, int from_tty) +{ + help_list (tui_window_cmds, "tui window ", all_commands, gdb_stdout); +} + /* Function to initialize gdb commands, for tui window manipulation. */ @@ -995,8 +1007,11 @@ _initialize_tui_win () &tui_setlist, &tui_showlist, &setlist, &showlist); - add_com ("refresh", class_tui, tui_refresh_all_command, - _("Refresh the terminal display.")); + cmd_list_element *refresh_cmd + = add_cmd ("refresh", class_tui, tui_refresh_all_command, + _("Refresh the terminal display."), + tui_get_cmd_list ()); + add_com_alias ("refresh", refresh_cmd, class_tui, 0); cmd_list_element *tabset_cmd = add_com ("tabset", class_tui, tui_set_tab_width_command, _("\ @@ -1004,21 +1019,30 @@ Set the width (in characters) of tab stops.\n\ Usage: tabset N")); deprecate_cmd (tabset_cmd, "set tui tab-width"); + /* Setup the 'tui window' list of command. */ + add_prefix_cmd ("window", class_tui, tui_window_command, + _("Text User Interface window commands."), + &tui_window_cmds, 1, tui_get_cmd_list ()); + cmd_list_element *winheight_cmd - = add_com ("winheight", class_tui, tui_set_win_height_command, _("\ + = add_cmd ("height", class_tui, tui_set_win_height_command, _("\ Set or modify the height of a specified window.\n\ -Usage: winheight WINDOW-NAME [+ | -] NUM-LINES\n\ -Use \"info win\" to see the names of the windows currently being displayed.")); +Usage: tui window height WINDOW-NAME [+ | -] NUM-LINES\n\ +Use \"info win\" to see the names of the windows currently being displayed."), + &tui_window_cmds); + add_com_alias ("winheight", winheight_cmd, class_tui, 0); add_com_alias ("wh", winheight_cmd, class_tui, 0); set_cmd_completer (winheight_cmd, winheight_completer); add_info ("win", tui_all_windows_info, _("List of all displayed windows.\n\ Usage: info win")); cmd_list_element *focus_cmd - = add_com ("focus", class_tui, tui_set_focus_command, _("\ + = add_cmd ("focus", class_tui, tui_set_focus_command, _("\ Set focus to named window or next/prev window.\n\ -Usage: focus [WINDOW-NAME | next | prev]\n\ -Use \"info win\" to see the names of the windows currently being displayed.")); +Usage: tui focus [WINDOW-NAME | next | prev]\n\ +Use \"info win\" to see the names of the windows currently being displayed."), + tui_get_cmd_list ()); + add_com_alias ("focus", focus_cmd, class_tui, 0); add_com_alias ("fs", focus_cmd, class_tui, 0); set_cmd_completer (focus_cmd, focus_completer); add_com ("+", class_tui, tui_scroll_forward_command, _("\ -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 01/15] gdb: move some commands into the tui namespace Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess ` (13 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess Rename tui_layout_base::adjust_size to tui_layout_base::set_height, the new name more accurately reflects what this member function does, and makes it easier for a later commit to add a new tui_layout_base::set_width member function. There should be no user visible changes after this commit. --- gdb/tui/tui-layout.c | 6 +++--- gdb/tui/tui-layout.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index f8388e3fca5..4c355c79d65 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -118,7 +118,7 @@ tui_apply_current_layout () void tui_adjust_window_height (struct tui_win_info *win, int new_height) { - applied_layout->adjust_size (win->name (), new_height); + applied_layout->set_height (win->name (), new_height); } /* Set the current layout to LAYOUT. */ @@ -570,7 +570,7 @@ tui_layout_split::set_weights_from_heights () /* See tui-layout.h. */ tui_adjust_result -tui_layout_split::adjust_size (const char *name, int new_height) +tui_layout_split::set_height (const char *name, int new_height) { /* Look through the children. If one is a layout holding the named window, we're done; or if one actually is the named window, @@ -579,7 +579,7 @@ tui_layout_split::adjust_size (const char *name, int new_height) for (int i = 0; i < m_splits.size (); ++i) { tui_adjust_result adjusted - = m_splits[i].layout->adjust_size (name, new_height); + = m_splits[i].layout->set_height (name, new_height); if (adjusted == HANDLED) return HANDLED; if (adjusted == FOUND) diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index b9a5d9b898d..acea7ac8f64 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -75,9 +75,9 @@ class tui_layout_base return nullptr; } - /* Adjust the size of the window named NAME to NEW_HEIGHT, updating + /* Set the height of the window named NAME to NEW_HEIGHT, updating the sizes of the other windows around it. */ - virtual tui_adjust_result adjust_size (const char *name, int new_height) = 0; + virtual tui_adjust_result set_height (const char *name, int new_height) = 0; /* Remove some windows from the layout, leaving the command window and the window being passed in here. */ @@ -127,7 +127,7 @@ class tui_layout_window : public tui_layout_base return m_contents.c_str (); } - tui_adjust_result adjust_size (const char *name, int new_height) override + tui_adjust_result set_height (const char *name, int new_height) override { return m_contents == name ? FOUND : NOT_FOUND; } @@ -192,7 +192,7 @@ class tui_layout_split : public tui_layout_base void apply (int x, int y, int width, int height) override; - tui_adjust_result adjust_size (const char *name, int new_height) override; + tui_adjust_result set_height (const char *name, int new_height) override; bool top_boxed_p () const override; -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 01/15] gdb: move some commands into the tui namespace Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess ` (12 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess In a following commit I'm going to add the ability to change the width of a tui window (when in a horizontal layout). As a result, some of the places where we currently hard-code references to height need to be changed to handle either height, or width, based on whether we are in a vertical, or horizontal layout. This commit renames set_weights_from_heights to set_weights_from_sizes, and makes the function use either the height, or width as appropriate. Currently, the only place that we call this function is from the tui_layout_split::set_height function, in a part of the code we will only reach for vertical layouts, so the new code is not actually being used, but, this small change will help make later patches smaller, so I'm proposing this as a stand alone change. There should be no user visible changes after this commit. --- gdb/tui/tui-layout.c | 9 +++++---- gdb/tui/tui-layout.h | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 4c355c79d65..9e856ccf3fa 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -561,10 +561,11 @@ tui_layout_split::bottom_boxed_p () const /* See tui-layout.h. */ void -tui_layout_split::set_weights_from_heights () +tui_layout_split::set_weights_from_sizes () { for (int i = 0; i < m_splits.size (); ++i) - m_splits[i].weight = m_splits[i].layout->height; + m_splits[i].weight + = m_vertical ? m_splits[i].layout->height : m_splits[i].layout->width; } /* See tui-layout.h. */ @@ -596,7 +597,7 @@ tui_layout_split::set_height (const char *name, int new_height) if (m_splits[found_index].layout->height == new_height) return HANDLED; - set_weights_from_heights (); + set_weights_from_sizes (); int delta = m_splits[found_index].weight - new_height; m_splits[found_index].weight = new_height; @@ -634,7 +635,7 @@ tui_layout_split::set_height (const char *name, int new_height) { warning (_("Invalid window height specified")); /* Effectively undo any modifications made here. */ - set_weights_from_heights (); + set_weights_from_sizes (); } else { diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index acea7ac8f64..8f41835b94c 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -217,8 +217,9 @@ class tui_layout_split : public tui_layout_base private: - /* Set the weights from the current heights. */ - void set_weights_from_heights (); + /* Set the weights from the current heights (when m_vertical is true) or + widths (when m_vertical is false). */ + void set_weights_from_sizes (); struct split { -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 04/15] gdb/testing/tui: add new functionality to tuiterm.exp 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (2 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess ` (11 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess While working on later patches in this series, I was running into csi control codes being emitted from ncurses that are not currently handled by out gdb/testsuite/lib/tuiterm.exp. This commit adds support for these additional control sequences. The new sequences are 'Insert Line', 'Delete Characters', and 'Scroll Down'. There are no new tests in this commit, but I was running into these sequences while developing later patches in this series. However, which control sequences ncurses emits can vary wildly depending on the screen contents. It is possible that I only hit some of these sequences while debugging the later patches (i.e. printing extra content to the terminal), some of these might no longer be needed given the tests as now written. Still, I think it is worth merging these to improve tuiterm.exp. Additionally, I noticed a bug in 'Erase in Line' that this commit fixes; in mode 1 the erase should be from the start of the line through to the cursor, not to the character before the cursor. This bug would mean that random characters would sometimes be left in the terminal output. --- gdb/testsuite/lib/tuiterm.exp | 82 ++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp index 38948015e96..06d2e091ca5 100644 --- a/gdb/testsuite/lib/tuiterm.exp +++ b/gdb/testsuite/lib/tuiterm.exp @@ -317,13 +317,40 @@ namespace eval Term { # From cursor to end. _clear_in_line $_cur_col $_cols $_cur_row } elseif {$arg == 1} { - _clear_in_line 0 $_cur_col $_cur_row + _clear_in_line 0 [expr $_cur_col + 1] $_cur_row } elseif {$arg == 2} { _clear_in_line 0 $_cols $_cur_row } } } + # Insert Line + # + # https://vt100.net/docs/vt510-rm/IL.html + proc _csi_L {args} { + set arg [_default [lindex $args 0] 1] + + _log_cur "Insert Line ($arg)" { + variable _cur_col + variable _cur_row + variable _rows + variable _cols + variable _chars + + set y [expr $_rows - 2] + set next_y [expr $y + 1] + while {$y >= $_cur_row} { + for {set x 0} {$x < $_cols} {incr x} { + set _chars($x,$next_y) $_chars($x,$y) + } + incr y -1 + incr next_y -1 + } + + _clear_lines $_cur_row $_rows + } + } + # Delete line. # # https://vt100.net/docs/vt510-rm/DL.html @@ -349,6 +376,59 @@ namespace eval Term { } } + # Delete Characters + # + # https://vt100.net/docs/vt510-rm/DCH.html + proc _csi_P {args} { + set count [_default [lindex $args 0] 1] + + _log_cur "Delete Character ($count)" { + variable _cur_col + variable _cur_row + variable _cols + variable _chars + + set dx [expr $_cur_col + 1] + set sx [expr $_cur_col + 1 + $count] + set y $_cur_row + + while {$sx < $_cols} { + set _chars($dx,$y) $_chars($sx,$y) + incr sx + incr dx + } + _clear_in_line $dx $sx $y + } + } + + # Pan Down + # + # https://vt100.net/docs/vt510-rm/SU.html + proc _csi_S {args} { + set count [_default [lindex $args 0] 1] + + _log_cur "Pan Down ($count)" { + variable _cur_col + variable _cur_row + variable _cols + variable _rows + variable _chars + + set dy 0 + set y $count + + while {$y < $_rows} { + for {set x 0} {$x < $_cols} {incr x} { + set _chars($x,$dy) $_chars($x,$y) + } + incr y 1 + incr dy 1 + } + + _clear_lines $dy $_rows + } + } + # Erase chars. # # https://vt100.net/docs/vt510-rm/ECH.html -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (3 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 06/15] gdb/tui: add a tui debugging flag Andrew Burgess ` (10 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit adds a new command 'tui window width', and an alias 'winwidth'. This command is equivalent to the old 'winheight' command (which was recently renamed 'tui window height'). Even though I recently moved the old tui commands under the tui namespace, and I would strongly encourage all new tui commands to be added as 'tui ....' only (users can create their own top-level aliases if they want), I'm breaking that suggestion here, and adding a 'winwidth' alias. Given that we already have 'winheight' and have done for years, it just didn't seem right to no have the matching 'winwidth'. You might notice in the test that the window resizing doesn't quite work right. I setup a horizontal layout, then grow and shrink the windows. At the end of the test the windows should be back to their original size... ... they are not. This isn't my fault, honest! GDB's window resizing is a little ... temperamental, and is prone to getting things slightly wrong during resizes, off by 1 type things. This is true for height resizing, as well as the new width resizing. Later patches in this series will rework the resizing algorithm, which should improve things in this area. For now, I'm happy that the width resizing is as good as the height resizing, given the existing quirks. For the docs side I include a paragraph that explains how multiple windows are required before the width can be adjusted. For completeness, I've added the same paragraph to the winheight description. With the predefined layouts this extra paragraph is not really needed for winheight, as there are always multiple windows on the screen. However, with custom layouts, this might not be true, so adding the paragraph seems like a good idea. As for the changes in gdb itself, I've mostly just taken the existing height adjustment code, changed the name to make it generic 'size' adjustment, and added a boolean flag to indicate if we are adjusting the width or the height. --- gdb/NEWS | 6 +++ gdb/doc/gdb.texinfo | 22 ++++++++++ gdb/testsuite/gdb.tui/winwidth.exp | 62 +++++++++++++++++++++++++++ gdb/tui/tui-layout.c | 33 +++++++++++---- gdb/tui/tui-layout.h | 34 ++++++++++++++- gdb/tui/tui-win.c | 68 +++++++++++++++++++++++++++--- 6 files changed, 209 insertions(+), 16 deletions(-) create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp diff --git a/gdb/NEWS b/gdb/NEWS index 3c3e0bbb2fb..1275d967a2d 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -127,6 +127,12 @@ tui window height and 'winheight' tui commands respectively. The old names still exist as aliases to these new commands. +tui window width +winwidth + The new command 'tui window width', and the alias 'winwidth' allow + the width of a tui window to be adjusted when windows are laid out + in horizontal mode. + * Changed commands maint packet diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index fd4c110569e..6081aa85af4 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -29115,6 +29115,28 @@ it. The @var{name} parameter can be the name of any currently visible window. The names of the currently visible windows can be discovered using @kbd{info win} (@pxref{info_win_command,,info win}). + +The set of currently visible windows must always fill the terminal, +and so, it is only possible to resize on window if there are other +visible windows that can either give or receive the extra terminal +space. + +@kindex tui window width +@kindex winwidth +@item tui window width @var{name} +@var{count} +@itemx tui window width @var{name} -@var{count} +@itemx winwidth @var{name} +@var{count} +@itemx winwidth @var{name} -@var{count} +Change the width of the window @var{name} by @var{count} columns. +Positive counts increase the width, while negative counts decrease it. +The @var{name} parameter can be the name of any currently visible +window. The names of the currently visible windows can be discovered +using @code{info win} (@pxref{info_win_command,,info win}). + +The set of currently visible windows must always fill the terminal, +and so, it is only possible to resize on window if there are other +visible windows that can either give or receive the extra terminal +space. @end table @node TUI Configuration diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp new file mode 100644 index 00000000000..b0a838b578f --- /dev/null +++ b/gdb/testsuite/gdb.tui/winwidth.exp @@ -0,0 +1,62 @@ +# Copyright 2022 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test the "winwidth" command. + +tuiterm_env + +standard_testfile tui-layout.c + +if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} { + return -1 +} + +Term::clean_restart 24 80 $testfile +if {![Term::enter_tui]} { + unsupported "TUI not supported" + return +} + +Term::command "tui new-layout h { -horizontal src 1 asm 1 } 1 status 0 cmd 1" +Term::command "layout h" + +with_test_prefix "original window sizes" { + Term::check_box "source box" 0 0 40 15 + Term::check_box "asm box" 39 0 41 15 + Term::command "winwidth src +5" +} + +with_test_prefix "after src +5" { + Term::check_box "source box" 0 0 44 15 + Term::check_box "asm box" 43 0 37 15 + Term::command "winwidth asm -5" +} + +with_test_prefix "after asm -5" { + Term::check_box "source box" 0 0 48 15 + Term::check_box "asm box" 47 0 33 15 + Term::command "winwidth asm +8" +} + +with_test_prefix "after asm +8" { + Term::check_box "source box" 0 0 39 15 + Term::check_box "asm box" 38 0 42 15 + Term::command "winwidth src -2" +} + +with_test_prefix "after src -2" { + Term::check_box "source box" 0 0 36 15 + Term::check_box "asm box" 35 0 45 15 +} diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 9e856ccf3fa..4e5740fd6d3 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -121,6 +121,14 @@ tui_adjust_window_height (struct tui_win_info *win, int new_height) applied_layout->set_height (win->name (), new_height); } +/* See tui-layout. */ + +void +tui_adjust_window_width (struct tui_win_info *win, int new_width) +{ + applied_layout->set_width (win->name (), new_width); +} + /* Set the current layout to LAYOUT. */ static void @@ -571,7 +579,7 @@ tui_layout_split::set_weights_from_sizes () /* See tui-layout.h. */ tui_adjust_result -tui_layout_split::set_height (const char *name, int new_height) +tui_layout_split::set_size (const char *name, int new_size, bool set_width_p) { /* Look through the children. If one is a layout holding the named window, we're done; or if one actually is the named window, @@ -579,13 +587,16 @@ tui_layout_split::set_height (const char *name, int new_height) int found_index = -1; for (int i = 0; i < m_splits.size (); ++i) { - tui_adjust_result adjusted - = m_splits[i].layout->set_height (name, new_height); + tui_adjust_result adjusted; + if (set_width_p) + adjusted = m_splits[i].layout->set_width (name, new_size); + else + adjusted = m_splits[i].layout->set_height (name, new_size); if (adjusted == HANDLED) return HANDLED; if (adjusted == FOUND) { - if (!m_vertical) + if (set_width_p ? m_vertical : !m_vertical) return FOUND; found_index = i; break; @@ -594,12 +605,15 @@ tui_layout_split::set_height (const char *name, int new_height) if (found_index == -1) return NOT_FOUND; - if (m_splits[found_index].layout->height == new_height) + int curr_size = (set_width_p + ? m_splits[found_index].layout->width + : m_splits[found_index].layout->height); + if (curr_size == new_size) return HANDLED; set_weights_from_sizes (); - int delta = m_splits[found_index].weight - new_height; - m_splits[found_index].weight = new_height; + int delta = m_splits[found_index].weight - new_size; + m_splits[found_index].weight = new_size; /* Distribute the "delta" over the next window; but if the next window cannot hold it all, keep going until we either find a @@ -633,7 +647,10 @@ tui_layout_split::set_height (const char *name, int new_height) if (delta != 0) { - warning (_("Invalid window height specified")); + if (set_width_p) + warning (_("Invalid window width specified")); + else + warning (_("Invalid window height specified")); /* Effectively undo any modifications made here. */ set_weights_from_sizes (); } diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index 8f41835b94c..79ad0b8dafc 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -79,6 +79,10 @@ class tui_layout_base the sizes of the other windows around it. */ virtual tui_adjust_result set_height (const char *name, int new_height) = 0; + /* Set the width of the window named NAME to NEW_WIDTH, updating + the sizes of the other windows around it. */ + virtual tui_adjust_result set_width (const char *name, int new_width) = 0; + /* Remove some windows from the layout, leaving the command window and the window being passed in here. */ virtual void remove_windows (const char *name) = 0; @@ -132,6 +136,11 @@ class tui_layout_window : public tui_layout_base return m_contents == name ? FOUND : NOT_FOUND; } + tui_adjust_result set_width (const char *name, int new_width) override + { + return m_contents == name ? FOUND : NOT_FOUND; + } + bool top_boxed_p () const override; bool bottom_boxed_p () const override; @@ -192,7 +201,17 @@ class tui_layout_split : public tui_layout_base void apply (int x, int y, int width, int height) override; - tui_adjust_result set_height (const char *name, int new_height) override; + tui_adjust_result set_height (const char *name, int new_height) override + { + /* Pass false as the final argument to indicate change of height. */ + return set_size (name, new_height, false); + } + + tui_adjust_result set_width (const char *name, int new_width) override + { + /* Pass true as the final argument to indicate change of width. */ + return set_size (name, new_width, true); + } bool top_boxed_p () const override; @@ -217,6 +236,15 @@ class tui_layout_split : public tui_layout_base private: + /* Used to implement set_height and set_width member functions. When + SET_WIDTH_P is true, set the width, otherwise, set the height of the + window named NAME to NEW_SIZE, updating the sizes of the other windows + around it as needed. The result indicates if the window NAME was + found and had its size adjusted, was found but was not adjusted, or + was not found at all. */ + tui_adjust_result set_size (const char *name, int new_size, + bool set_width_p); + /* Set the weights from the current heights (when m_vertical is true) or widths (when m_vertical is false). */ void set_weights_from_sizes (); @@ -266,6 +294,10 @@ extern void tui_apply_current_layout (); extern void tui_adjust_window_height (struct tui_win_info *win, int new_height); +/* Adjust the window width of WIN to NEW_WIDTH. */ +extern void tui_adjust_window_width (struct tui_win_info *win, + int new_width); + /* The type of a function that is used to create a TUI window. */ typedef std::function<tui_win_info * (const char *name)> window_factory; diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index ba6aca3d078..512ea52b694 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -842,10 +842,21 @@ tui_set_tab_width_command (const char *arg, int from_tty) } } +/* Helper function for the user commands to adjust a window's width or + height. The ARG string contains the command line arguments from the + user, which should give the name of a window, and how to adjust the + size. + + When SET_WIDTH_P is true the width of the window is adjusted based on + ARG, and when SET_WIDTH_P is false, the height of the window is adjusted + based on ARG. + + On invalid input, or if the size can't be adjusted as requested, then an + error is thrown, otherwise, the window sizes are adjusted, and the + windows redrawn. */ -/* Set the height of the specified window. */ static void -tui_set_win_height_command (const char *arg, int from_tty) +tui_set_win_size (const char *arg, bool set_width_p) { /* Make sure the curses mode is enabled. */ tui_enable (); @@ -854,7 +865,7 @@ tui_set_win_height_command (const char *arg, int from_tty) const char *buf = arg; const char *buf_ptr = buf; - int new_height; + int new_size; struct tui_win_info *win_info; buf_ptr = skip_to_space (buf_ptr); @@ -890,20 +901,53 @@ tui_set_win_height_command (const char *arg, int from_tty) if (negate) input_no *= (-1); if (fixed_size) - new_height = input_no; + new_size = input_no; else - new_height = win_info->height + input_no; + { + int curr_size; + if (set_width_p) + curr_size = win_info->width; + else + curr_size = win_info->height; + new_size = curr_size + input_no; + } /* Now change the window's height, and adjust all other windows around it. */ - tui_adjust_window_height (win_info, new_height); + if (set_width_p) + tui_adjust_window_width (win_info, new_size); + else + tui_adjust_window_height (win_info, new_size); tui_update_gdb_sizes (); } else - error (_("Invalid window height specified")); + { + if (set_width_p) + error (_("Invalid window width specified")); + else + error (_("Invalid window height specified")); + } } } +/* Implement the 'tui window height' command (alias 'winheight'). */ + +static void +tui_set_win_height_command (const char *arg, int from_tty) +{ + /* Pass false as the final argument to set the height. */ + tui_set_win_size (arg, false); +} + +/* Implement the 'tui window width' command (alias 'winwidth'). */ + +static void +tui_set_win_width_command (const char *arg, int from_tty) +{ + /* Pass true as the final argument to set the width. */ + tui_set_win_size (arg, true); +} + /* See tui-data.h. */ int @@ -1033,6 +1077,16 @@ Use \"info win\" to see the names of the windows currently being displayed."), add_com_alias ("winheight", winheight_cmd, class_tui, 0); add_com_alias ("wh", winheight_cmd, class_tui, 0); set_cmd_completer (winheight_cmd, winheight_completer); + + cmd_list_element *winwidth_cmd + = add_cmd ("width", class_tui, tui_set_win_width_command, _("\ +Set or modify the width of a specified window.\n\ +Usage: tui window width WINDOW-NAME [+ | -] NUM-LINES\n\ +Use \"info win\" to see the names of the windows currently being displayed."), + &tui_window_cmds); + add_com_alias ("winwidth", winwidth_cmd, class_tui, 0); + set_cmd_completer (winwidth_cmd, winheight_completer); + add_info ("win", tui_all_windows_info, _("List of all displayed windows.\n\ Usage: info win")); -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 06/15] gdb/tui: add a tui debugging flag 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (4 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-08 12:16 ` Eli Zaretskii 2022-03-07 22:13 ` [PATCHv3 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess ` (9 subsequent siblings) 15 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit adds 'set debug tui on|off' and 'show debug tui'. This commit adds the control variable, and the printing macros in tui/tui.h. I've then added some uses of these in tui.c and tui-layout.c. To help produce more useful debug output in tui-layout.c, I've added some helper member functions in the class tui_layout_split, and also moved the size_info struct out of tui_layout_split::apply into the tui_layout_split class. If tui debug is not turned on, then there should be no user visible changes after this commit. One thing to note is that, due to the way that the tui terminal is often cleared, the only way I've found this useful is when I do: (gdb) tui enable (gdb) set logging file /path/to/file (gdb) set logging debugredirect on (gdb) set logging enable on Additionally, gdb has some quirks when it comes to setting up logging redirect and switching interpreters. Thus, the above only really works if the logging is enabled after the tui is enabled, and disabled again before the tui is disabled. Enabling logging and switching interpreters can cause undefined results, including crashes. This is an existing bug in gdb[1], and has nothing directly to do with tui debug, but it is worth mentioning here I think. [1] https://sourceware.org/bugzilla/show_bug.cgi?id=28948 --- gdb/NEWS | 4 ++ gdb/doc/gdb.texinfo | 11 +++++ gdb/tui/tui-layout.c | 99 +++++++++++++++++++++++++++++++++++++++----- gdb/tui/tui-layout.h | 25 +++++++++++ gdb/tui/tui.c | 26 ++++++++++++ gdb/tui/tui.h | 14 +++++++ 6 files changed, 168 insertions(+), 11 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 1275d967a2d..eb18ac47804 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -133,6 +133,10 @@ winwidth the width of a tui window to be adjusted when windows are laid out in horizontal mode. +set debug tui on|off +show debug tui + Control the display of debug output about GDB's tui. + * Changed commands maint packet diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6081aa85af4..60173e07747 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -29205,6 +29205,17 @@ source text at the next tab stop; the compact display uses only as much space as is needed for the line numbers in the current file, and only a single space to separate the line numbers from the source. + +@kindex set debug tui +@item set debug tui @r{[}on|off@r{]} +Turn on or off display of @value{GDBN} internal debug messages relating +to the TUI. + +@kindex show debug tui +@item show debug tui +Show the current status of displaying @value{GDBN} internal debug +messages relating to the TUI. + @end table Note that the colors of the TUI borders can be controlled using the diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 4e5740fd6d3..8e8b4538c7e 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -426,8 +426,14 @@ tui_layout_window::apply (int x_, int y_, int width_, int height_) void tui_layout_window::get_sizes (bool height, int *min_value, int *max_value) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + if (m_window == nullptr) m_window = tui_get_window_by_name (m_contents); + + tui_debug_printf ("window = %s, getting %s", + m_window->name (), (height ? "height" : "width")); + if (height) { *min_value = m_window->min_height (); @@ -438,6 +444,8 @@ tui_layout_window::get_sizes (bool height, int *min_value, int *max_value) *min_value = m_window->min_width (); *max_value = m_window->max_width (); } + + tui_debug_printf ("min = %d, max = %d", *min_value, *max_value); } /* See tui-layout.h. */ @@ -522,6 +530,8 @@ tui_layout_split::clone () const void tui_layout_split::get_sizes (bool height, int *min_value, int *max_value) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + *min_value = 0; *max_value = 0; bool first_time = true; @@ -544,6 +554,8 @@ tui_layout_split::get_sizes (bool height, int *min_value, int *max_value) } first_time = false; } + + tui_debug_printf ("min_value = %d, max_value = %d", *min_value, *max_value); } /* See tui-layout.h. */ @@ -578,9 +590,46 @@ tui_layout_split::set_weights_from_sizes () /* See tui-layout.h. */ +std::string +tui_layout_split::tui_debug_weights_to_string () const +{ + std::string str; + + for (int i = 0; i < m_splits.size (); ++i) + { + if (i > 0) + str += ", "; + str += string_printf ("[%d] %d", i, m_splits[i].weight); + } + + return str; +} + +/* See tui-layout.h. */ + +void +tui_layout_split::tui_debug_print_size_info + (const std::vector<tui_layout_split::size_info> &info) +{ + gdb_assert (debug_tui); + + tui_debug_printf ("current size info data:"); + for (int i = 0; i < info.size (); ++i) + tui_debug_printf (" [%d] { size = %d, min = %d, max = %d, share_box = %d }", + i, info[i].size, info[i].min_size, + info[i].max_size, info[i].share_box); +} + +/* See tui-layout.h. */ + tui_adjust_result tui_layout_split::set_size (const char *name, int new_size, bool set_width_p) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + + tui_debug_printf ("this = %p, name = %s, new_size = %d", + this, name, new_size); + /* Look through the children. If one is a layout holding the named window, we're done; or if one actually is the named window, update it. */ @@ -611,10 +660,15 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p) if (curr_size == new_size) return HANDLED; + tui_debug_printf ("found window %s at index %d", name, found_index); + set_weights_from_sizes (); int delta = m_splits[found_index].weight - new_size; m_splits[found_index].weight = new_size; + tui_debug_printf ("before delta (%d) distribution, weights: %s", + delta, tui_debug_weights_to_string ().c_str ()); + /* Distribute the "delta" over the next window; but if the next window cannot hold it all, keep going until we either find a window that does, or until we loop all the way around. */ @@ -643,8 +697,14 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p) m_splits[index].weight += grow_by; delta -= grow_by; } + + tui_debug_printf ("index = %d, weight now: %d", + index, m_splits[index].weight); } + tui_debug_printf ("after delta (%d) distribution, weights: %s", + delta, tui_debug_weights_to_string ().c_str ()); + if (delta != 0) { if (set_width_p) @@ -668,23 +728,18 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p) void tui_layout_split::apply (int x_, int y_, int width_, int height_) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + x = x_; y = y_; width = width_; height = height_; - struct size_info - { - int size; - int min_size; - int max_size; - /* True if this window will share a box border with the previous - window in the list. */ - bool share_box; - }; - std::vector<size_info> info (m_splits.size ()); + tui_debug_printf ("weights are: %s", + tui_debug_weights_to_string ().c_str ()); + /* Step 1: Find the min and max size of each sub-layout. Fixed-sized layouts are given their desired size, and then the remaining space is distributed among the remaining windows @@ -760,9 +815,31 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) } } + if (debug_tui) + { + tui_debug_printf ("after initial size calculation"); + tui_debug_printf ("available_size = %d, used_size = %d", + available_size, used_size); + tui_debug_printf ("total_weight = %d, last_index = %d", + total_weight, last_index); + tui_debug_print_size_info (info); + } + /* Allocate any leftover size. */ if (available_size >= used_size && last_index != -1) - info[last_index].size += available_size - used_size; + { + info[last_index].size += available_size - used_size; + + if (debug_tui) + { + tui_debug_printf ("after final size calculation"); + tui_debug_printf ("available_size = %d, used_size = %d", + available_size, used_size); + tui_debug_printf ("total_weight = %d, last_index = %d", + total_weight, last_index); + tui_debug_print_size_info (info); + } + } /* Step 3: Resize. */ int size_accum = 0; diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index 79ad0b8dafc..26de3c3a979 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -249,6 +249,31 @@ class tui_layout_split : public tui_layout_base widths (when m_vertical is false). */ void set_weights_from_sizes (); + /* Structure used when resizing, or applying a layout. An instance of + this structure is created for each sub-layout. */ + struct size_info + { + /* The calculated size for this sub-layout. */ + int size; + + /* The minimum and maximum sizes for this sub-layout, obtained by + calling the get_sizes member function. */ + int min_size; + int max_size; + + /* True if this window will share a box border with the previous + window in the list. */ + bool share_box; + }; + + /* Used for debug, prints the contents of INFO using tui_debug_printf. + Only call this when the global debug_tui is true. */ + static void tui_debug_print_size_info (const std::vector<size_info> &info); + + /* Used for debug, returns a string describing the current weight of each + sub-layout. */ + std::string tui_debug_weights_to_string () const; + struct split { /* The requested weight. */ diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c index 776dccf0bb2..6332eceb4af 100644 --- a/gdb/tui/tui.c +++ b/gdb/tui/tui.c @@ -50,6 +50,19 @@ #include "gdb_curses.h" #include "interps.h" +/* See tui.h. */ + +bool debug_tui = false; + +/* Implement 'show debug tui'. */ + +static void +show_tui_debug (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("TUI debugging is \"%s\".\n"), value); +} + /* This redefines CTRL if it is not already defined, so it must come after terminal state releated include files like <term.h> and "gdb_curses.h". */ @@ -354,6 +367,8 @@ gdb_getenv_term (void) void tui_enable (void) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + if (tui_active) return; @@ -494,6 +509,8 @@ tui_enable (void) void tui_disable (void) { + TUI_SCOPED_DEBUG_ENTER_EXIT; + if (!tui_active) return; @@ -587,4 +604,13 @@ Usage: tui enable"), _("Disable TUI display mode.\n\ Usage: tui disable"), tuicmd); + + /* Debug this tui internals. */ + add_setshow_boolean_cmd ("tui", class_maintenance, &debug_tui, _("\ +Set tui debugging."), _("\ +Show tui debugging."), _("\ +When true, tui specific internal debugging is enabled."), + NULL, + show_tui_debug, + &setdebuglist, &showdebuglist); } diff --git a/gdb/tui/tui.h b/gdb/tui/tui.h index a4df66f17fc..924d91daa7e 100644 --- a/gdb/tui/tui.h +++ b/gdb/tui/tui.h @@ -22,6 +22,20 @@ #ifndef TUI_TUI_H #define TUI_TUI_H +/* Flag to control tui debugging. */ + +extern bool debug_tui; + +/* Print a "tui" debug statement. */ + +#define tui_debug_printf(fmt, ...) \ + debug_prefixed_printf_cond (debug_tui, "tui", fmt, ##__VA_ARGS__) + +/* Print "tui" enter/exit debug statements. */ + +#define TUI_SCOPED_DEBUG_ENTER_EXIT \ + scoped_debug_enter_exit (debug_tui, "tui") + struct ui_file; /* Types of error returns. */ -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv3 06/15] gdb/tui: add a tui debugging flag 2022-03-07 22:13 ` [PATCHv3 06/15] gdb/tui: add a tui debugging flag Andrew Burgess @ 2022-03-08 12:16 ` Eli Zaretskii 2022-03-09 11:48 ` Andrew Burgess 0 siblings, 1 reply; 74+ messages in thread From: Eli Zaretskii @ 2022-03-08 12:16 UTC (permalink / raw) To: Andrew Burgess; +Cc: gdb-patches > Date: Mon, 7 Mar 2022 22:13:38 +0000 > From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> > Cc: Andrew Burgess <aburgess@redhat.com> > > diff --git a/gdb/NEWS b/gdb/NEWS > index 1275d967a2d..eb18ac47804 100644 > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -133,6 +133,10 @@ winwidth > the width of a tui window to be adjusted when windows are laid out > in horizontal mode. > > +set debug tui on|off > +show debug tui > + Control the display of debug output about GDB's tui. > + > * Changed commands > > maint packet > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > index 6081aa85af4..60173e07747 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -29205,6 +29205,17 @@ > source text at the next tab stop; the compact display uses only as > much space as is needed for the line numbers in the current file, and > only a single space to separate the line numbers from the source. > + > +@kindex set debug tui > +@item set debug tui @r{[}on|off@r{]} > +Turn on or off display of @value{GDBN} internal debug messages relating > +to the TUI. > + > +@kindex show debug tui > +@item show debug tui > +Show the current status of displaying @value{GDBN} internal debug > +messages relating to the TUI. > + The documentation parts are OK, but I wonder whether we should mention the caveats you described, at least in NEWS. I'm aware that we don't usually describe known bugs, but since you say this could cause crashes, perhaps it justifies an exception? Thanks. ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv3 06/15] gdb/tui: add a tui debugging flag 2022-03-08 12:16 ` Eli Zaretskii @ 2022-03-09 11:48 ` Andrew Burgess 2022-03-09 12:58 ` Eli Zaretskii 2022-03-09 17:53 ` Tom Tromey 0 siblings, 2 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-09 11:48 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches Eli Zaretskii via Gdb-patches <gdb-patches@sourceware.org> writes: >> Date: Mon, 7 Mar 2022 22:13:38 +0000 >> From: Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> >> Cc: Andrew Burgess <aburgess@redhat.com> >> >> diff --git a/gdb/NEWS b/gdb/NEWS >> index 1275d967a2d..eb18ac47804 100644 >> --- a/gdb/NEWS >> +++ b/gdb/NEWS >> @@ -133,6 +133,10 @@ winwidth >> the width of a tui window to be adjusted when windows are laid out >> in horizontal mode. >> >> +set debug tui on|off >> +show debug tui >> + Control the display of debug output about GDB's tui. >> + >> * Changed commands >> >> maint packet >> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo >> index 6081aa85af4..60173e07747 100644 >> --- a/gdb/doc/gdb.texinfo >> +++ b/gdb/doc/gdb.texinfo >> @@ -29205,6 +29205,17 @@ >> source text at the next tab stop; the compact display uses only as >> much space as is needed for the line numbers in the current file, and >> only a single space to separate the line numbers from the source. >> + >> +@kindex set debug tui >> +@item set debug tui @r{[}on|off@r{]} >> +Turn on or off display of @value{GDBN} internal debug messages relating >> +to the TUI. >> + >> +@kindex show debug tui >> +@item show debug tui >> +Show the current status of displaying @value{GDBN} internal debug >> +messages relating to the TUI. >> + > > The documentation parts are OK, but I wonder whether we should mention > the caveats you described, at least in NEWS. I'm aware that we don't > usually describe known bugs, but since you say this could cause > crashes, perhaps it justifies an exception? I don't know if that's really a route we want to start going down. Why would this bug deserve a NEWS entry over any other bug? Additionally, the 'set debug ...' flags are really only used for maintenance (I really with they were 'maint set debug ...', but they are what they are). My motivation for adding this text to the commit message is simply, that if a bug _was_ reported in this area, and a GDB maintainer tries to debug it, and they track it back to this commit ... then the commit message acknowledges that there is an issue here. Anyway, below is a patch that adds a NEWS entry for this bug. Let me know your thoughts. thanks, Andrew --- diff --git a/gdb/NEWS b/gdb/NEWS index 4d282cb37dd..166b7f57353 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -9,6 +9,11 @@ Python 2. From GDB 13, it will only be possible to build GDB itself with Python 3 support. +* Bug PR gdb/28948 exists, this can cause GDB to crash when logging + redirection is enabled, and the TUI interface is enabled and + disabled. See the following link for more details: + https://sourceware.org/bugzilla/show_bug.cgi?id=28948 + * Improved C++ template support GDB now treats functions/types involving C++ templates like it does function ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv3 06/15] gdb/tui: add a tui debugging flag 2022-03-09 11:48 ` Andrew Burgess @ 2022-03-09 12:58 ` Eli Zaretskii 2022-03-09 17:53 ` Tom Tromey 1 sibling, 0 replies; 74+ messages in thread From: Eli Zaretskii @ 2022-03-09 12:58 UTC (permalink / raw) To: Andrew Burgess; +Cc: gdb-patches > From: Andrew Burgess <aburgess@redhat.com> > Cc: gdb-patches@sourceware.org > Date: Wed, 09 Mar 2022 11:48:07 +0000 > > > The documentation parts are OK, but I wonder whether we should mention > > the caveats you described, at least in NEWS. I'm aware that we don't > > usually describe known bugs, but since you say this could cause > > crashes, perhaps it justifies an exception? > > I don't know if that's really a route we want to start going down. Why > would this bug deserve a NEWS entry over any other bug? Because users could crash their GDB session by doing completely innocent and reasonable things? But I see that the crashes are not related to the new setting you are adding, so I withdraw my suggestion to mention the crashes in NEWS. ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv3 06/15] gdb/tui: add a tui debugging flag 2022-03-09 11:48 ` Andrew Burgess 2022-03-09 12:58 ` Eli Zaretskii @ 2022-03-09 17:53 ` Tom Tromey 1 sibling, 0 replies; 74+ messages in thread From: Tom Tromey @ 2022-03-09 17:53 UTC (permalink / raw) To: Andrew Burgess via Gdb-patches; +Cc: Eli Zaretskii, Andrew Burgess >>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes: Andrew> Additionally, the 'set debug ...' flags are really only used for Andrew> maintenance (I really with they were 'maint set debug ...', but they Andrew> are what they are). I think that would be reasonable to change, actually. Tom ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (5 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 06/15] gdb/tui: add a tui debugging flag Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess ` (8 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess When I initially saw this code in tui_layout_split::apply, I assumed that this must be a bug: /* Two adjacent boxed windows will share a border, making a bit more size available. */ if (i > 0 && m_splits[i - 1].layout->bottom_boxed_p () && m_splits[i].layout->top_boxed_p ()) ... After all, the apply might be laying out a horizontal layout, right? So checking bottom_boxed_p and top_boxed_p is clearly wrong. Well, it turns on, that due to the implementations of these things, bottom_boxed_p is equivalent to an imagined right_boxed_p, and top_boxed_p is equivalent to an imagined left_boxed_p. In this commit I've renamed both top_boxed_p and bottom_boxed_p to first_edge_has_border_p and last_edge_has_border_p respectively, and extended the comments in tui_layout_base to mention that these methods handle both horizontal and vertical layouts. Now, hopefully, the code shouldn't look like it only applies for vertical layouts. There should be no user visible changes after this commit. --- gdb/tui/tui-layout.c | 16 ++++++++-------- gdb/tui/tui-layout.h | 18 ++++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 8e8b4538c7e..3e1c5804460 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -451,7 +451,7 @@ tui_layout_window::get_sizes (bool height, int *min_value, int *max_value) /* See tui-layout.h. */ bool -tui_layout_window::top_boxed_p () const +tui_layout_window::first_edge_has_border_p () const { gdb_assert (m_window != nullptr); return m_window->can_box (); @@ -460,7 +460,7 @@ tui_layout_window::top_boxed_p () const /* See tui-layout.h. */ bool -tui_layout_window::bottom_boxed_p () const +tui_layout_window::last_edge_has_border_p () const { gdb_assert (m_window != nullptr); return m_window->can_box (); @@ -561,21 +561,21 @@ tui_layout_split::get_sizes (bool height, int *min_value, int *max_value) /* See tui-layout.h. */ bool -tui_layout_split::top_boxed_p () const +tui_layout_split::first_edge_has_border_p () const { if (m_splits.empty ()) return false; - return m_splits[0].layout->top_boxed_p (); + return m_splits[0].layout->first_edge_has_border_p (); } /* See tui-layout.h. */ bool -tui_layout_split::bottom_boxed_p () const +tui_layout_split::last_edge_has_border_p () const { if (m_splits.empty ()) return false; - return m_splits.back ().layout->top_boxed_p (); + return m_splits.back ().layout->last_edge_has_border_p (); } /* See tui-layout.h. */ @@ -785,8 +785,8 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) /* Two adjacent boxed windows will share a border, making a bit more size available. */ if (i > 0 - && m_splits[i - 1].layout->bottom_boxed_p () - && m_splits[i].layout->top_boxed_p ()) + && m_splits[i - 1].layout->last_edge_has_border_p () + && m_splits[i].layout->first_edge_has_border_p ()) info[i].share_box = true; } diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index 26de3c3a979..9cfcfb8e81f 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -62,11 +62,13 @@ class tui_layout_base HEIGHT is true to fetch height, false to fetch width. */ virtual void get_sizes (bool height, int *min_value, int *max_value) = 0; - /* True if the topmost item in this layout is boxed. */ - virtual bool top_boxed_p () const = 0; + /* True if the topmost (for vertical layouts), or the leftmost (for + horizontal layouts) item in this layout is boxed. */ + virtual bool first_edge_has_border_p () const = 0; - /* True if the bottommost item in this layout is boxed. */ - virtual bool bottom_boxed_p () const = 0; + /* True if the bottommost (for vertical layouts), or the rightmost (for + horizontal layouts) item in this layout is boxed. */ + virtual bool last_edge_has_border_p () const = 0; /* Return the name of this layout's window, or nullptr if this layout does not represent a single window. */ @@ -141,9 +143,9 @@ class tui_layout_window : public tui_layout_base return m_contents == name ? FOUND : NOT_FOUND; } - bool top_boxed_p () const override; + bool first_edge_has_border_p () const override; - bool bottom_boxed_p () const override; + bool last_edge_has_border_p () const override; void remove_windows (const char *name) override { @@ -213,9 +215,9 @@ class tui_layout_split : public tui_layout_base return set_size (name, new_width, true); } - bool top_boxed_p () const override; + bool first_edge_has_border_p () const override; - bool bottom_boxed_p () const override; + bool last_edge_has_border_p () const override; void remove_windows (const char *name) override; -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 08/15] gdb/tui/testsuite: refactor new-layout.exp test 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (6 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess ` (7 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit changes the gdb.tui/new-layout.exp test to make use of a list of test descriptions, and a loop to check each description in turn. There's no change to what is actually tested after this commit. In future commits I plan to add additional tests to this file, and this will be easier now that all I have to do is add a new test description to the list. --- gdb/testsuite/gdb.tui/new-layout.exp | 83 +++++++++++++++++++--------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index 2b5e07db612..d3d34af7439 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -55,20 +55,39 @@ if { [tcl_version_at_least 8 6] } { "Missing '\}' in layout specification" } -gdb_test_no_output "tui new-layout example asm 1 status 0 cmd 1" - -gdb_test "help layout example" \ - "Apply the \"example\" layout.*tui new-layout example asm 1 status 0 cmd 1" - -gdb_test_no_output "tui new-layout example2 {asm 1 status 0} 1 cmd 1" - -gdb_test "help layout example2" \ - "Apply the \"example2\" layout.*tui new-layout example2 {asm 1 status 0} 1 cmd 1" - -gdb_test_no_output "tui new-layout h {-horizontal asm 1 src 1} 1 status 0 cmd 1" +# Each entry of this list describes a layout, and some associated +# tests. The items within each entry are: +# 1. layout name, +# 2. a string used to create the layout, +# 3. a list of boxes to check for once the layout is selected, +# 4. a regexp to match against the whole screen contents, this +# can be empty to skip this check. +set layouts \ + [list \ + [list example "asm 1 status 0 cmd 1" \ + {{0 0 80 15}} "$hex <main>"] \ + [list example2 "{asm 1 status 0} 1 cmd 1" \ + {{0 0 80 15}} ""] \ + [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \ + {{0 0 40 15} {39 0 41 15}} \ + "$hex <main>.*21.*return 0"]] + +# Helper function to verify a list of boxes. +proc check_boxes {boxes} { + set boxno 1 + foreach box $boxes { + eval Term::check_box [list "box $boxno"] $box + incr boxno + } +} -gdb_test "help layout h" \ - "Apply the \"h\" layout.*tui new-layout h {-horizontal asm 1 src 1} 1 status 0 cmd 1" +# Now create the layouts. +foreach layout $layouts { + lassign $layout name desc + gdb_test_no_output "tui new-layout $name $desc" + gdb_test "help layout $name" \ + "Apply the \"$name\" layout.*tui new-layout $name $desc" +} if {![Term::enter_tui]} { unsupported "TUI not supported" @@ -79,20 +98,30 @@ set text [Term::get_all_lines] gdb_assert {![string match "No Source Available" $text]} \ "initial source listing" -Term::command "layout example" -Term::check_contents "example layout shows assembly" \ - "$hex <main>" +foreach_with_prefix layout $layouts { + lassign $layout name desc boxes content_pattern + + # Reset the layout to a known starting configuration. + Term::command "layout src" + Term::command "winheight cmd 8" + + # Apply our test layout. + Term::command "layout $name" + check_boxes $boxes -Term::command "layout h" -Term::check_box "left window box" 0 0 40 15 -Term::check_box "right window box" 39 0 41 15 -Term::check_contents "horizontal display" \ - "$hex <main>.*21.*return 0" + if {$content_pattern != ""} { + Term::check_contents "contents in layout $name" \ + "${content_pattern}" + } -Term::command "winheight src - 5" -Term::check_box "left window box after shrink" 0 0 40 10 -Term::check_box "right window box after shrink" 39 0 41 10 + # Some additional tests for the 'h' layout. + if {$name == "h"} { + Term::command "winheight src - 5" + Term::check_box "left window box after shrink" 0 0 40 10 + Term::check_box "right window box after shrink" 39 0 41 10 -Term::command "winheight src + 5" -Term::check_box "left window box after grow" 0 0 40 15 -Term::check_box "right window box after grow" 39 0 41 15 + Term::command "winheight src + 5" + Term::check_box "left window box after grow" 0 0 40 15 + Term::check_box "right window box after grow" 39 0 41 15 + } +} -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 09/15] gdb/tui: avoid fp exception when applying layouts 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (7 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess ` (6 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess Consider: (gdb) tui enable (gdb) layout src (gdb) tui new-layout conly cmd 1 (gdb) layout conly After this, with current master, gdb crashes with a floating-point exception. The problem is that in tui_layout_split::apply, when we switch from 'src' to 'conly', we will try to retain the cmd window height. As such, the cmd window will become a fixed size window, which decreases the available_size, but doesn't count towards the total_weight. As the cmd window is the only window, the total_weight stays at zero, and, when we move into step 2, where we attempt to size the windows, we perform a divide by zero, and crash. After this commit we avoid the divide by zero, and just directly set the window size based on the fixed size. There is still a problem after this commit, when the conly layout is selected the cmd window retains its original height, which will only be part of the terminal. The rest of the terminal is left unused. This issue will be addressed in a later commit, this commit is just about the floating-point exception. --- gdb/testsuite/gdb.tui/new-layout.exp | 3 ++- gdb/tui/tui-layout.c | 30 ++++++++++++++++++---------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index d3d34af7439..66048e65238 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -70,7 +70,8 @@ set layouts \ {{0 0 80 15}} ""] \ [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \ {{0 0 40 15} {39 0 41 15}} \ - "$hex <main>.*21.*return 0"]] + "$hex <main>.*21.*return 0"] \ + [list cmd_only "cmd 1" {} ""]] # Helper function to verify a list of boxes. proc check_boxes {boxes} { diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 3e1c5804460..8758bfe70e7 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -790,29 +790,37 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) info[i].share_box = true; } + /* If last_index is set then we have a window that is not of a fixed + size. This window will have its size calculated below, which requires + that the total_weight not be zero (we divide by total_weight, so don't + want a floating-point exception). */ + gdb_assert (last_index == -1 || total_weight > 0); + /* Step 2: Compute the size of each sub-layout. Fixed-sized items are given their fixed size, while others are resized according to their weight. */ int used_size = 0; for (int i = 0; i < m_splits.size (); ++i) { - /* Compute the height and clamp to the allowable range. */ - info[i].size = available_size * m_splits[i].weight / total_weight; - if (info[i].size > info[i].max_size) - info[i].size = info[i].max_size; - if (info[i].size < info[i].min_size) - info[i].size = info[i].min_size; - /* If there is any leftover size, just redistribute it to the - last resizeable window, by dropping it from the allocated - size. We could try to be fancier here perhaps, by - redistributing this size among all windows, not just the - last window. */ if (info[i].min_size != info[i].max_size) { + /* Compute the height and clamp to the allowable range. */ + info[i].size = available_size * m_splits[i].weight / total_weight; + if (info[i].size > info[i].max_size) + info[i].size = info[i].max_size; + if (info[i].size < info[i].min_size) + info[i].size = info[i].min_size; + /* If there is any leftover size, just redistribute it to the + last resizeable window, by dropping it from the allocated + size. We could try to be fancier here perhaps, by + redistributing this size among all windows, not just the + last window. */ used_size += info[i].size; if (info[i].share_box) --used_size; } + else + info[i].size = info[i].min_size; } if (debug_tui) -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 10/15] gdb/tui: fairer distribution of excess space during apply 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (8 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess ` (5 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess When applying layouts gdb computes the size of each window (or rather, each sub-layout within a layout) using integer arithmetic. As this rounds down the results, then, when all sub-layouts are sized, there is the possibility that we have some space left over. Currently, this space is just assigned to an arbitrary sub-layout. This can result in some unbalanced results. Consider this set of steps with current master: (gdb) tui enable (gdb) layout regs (gdb) info win Name Lines Columns Focus regs 7 80 src 9 80 (has focus) status 1 80 cmd 8 80 Notice the weird split between the src and regs windows, the original layout specification has these windows given equal weight. The problem is that, with rounding, both the regs and src windows are initially sized to 7, the extra 2 lines are then arbitrarily added to the src window. In this commit, rather than add all the extra space to one single window, I instead hand out the extra space 1 line at a time, looping over all the sub-layouts. We take care to respect the min/max sizes, and so, we now get this result: (gdb) tui enable (gdb) layout regs (gdb) info win Name Lines Columns Focus regs 8 80 src 8 80 (has focus) status 1 80 cmd 8 80 This looks more natural to me. This is obviously a change in behaviour, and so, lots of the existing tests need to be updated to take this into account. None of the changes are huge, it's just a line or two (or column for width) moved between windows. --- gdb/testsuite/gdb.tui/basic.exp | 4 ++-- gdb/testsuite/gdb.tui/empty.exp | 14 +++++++---- gdb/testsuite/gdb.tui/regs.exp | 4 ++-- gdb/testsuite/gdb.tui/winwidth.exp | 17 ++++++------- gdb/tui/tui-layout.c | 38 ++++++++++++++++++++++++------ 5 files changed, 53 insertions(+), 24 deletions(-) diff --git a/gdb/testsuite/gdb.tui/basic.exp b/gdb/testsuite/gdb.tui/basic.exp index 0e9f2e3eab2..7afb28b0858 100644 --- a/gdb/testsuite/gdb.tui/basic.exp +++ b/gdb/testsuite/gdb.tui/basic.exp @@ -104,5 +104,5 @@ Term::command "layout split" Term::check_contents "split layout contents" \ "$main_line *$main_re.*$hex <main>" -Term::check_box "source box in split layout" 0 0 80 7 -Term::check_box "asm box in split layout" 0 6 80 9 +Term::check_box "source box in split layout" 0 0 80 8 +Term::check_box "asm box in split layout" 0 7 80 8 diff --git a/gdb/testsuite/gdb.tui/empty.exp b/gdb/testsuite/gdb.tui/empty.exp index ef14fe4dac0..3efa55d812e 100644 --- a/gdb/testsuite/gdb.tui/empty.exp +++ b/gdb/testsuite/gdb.tui/empty.exp @@ -35,26 +35,26 @@ if {![Term::enter_tui]} { set layouts { {src src {{0 0 80 15}} {{0 0 90 26}} {{"no source" "No Source Available"}}} - {regs src-regs {{0 0 80 7} {0 6 80 9}} {{0 0 90 13} {0 12 90 13}} + {regs src-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}} { {"no source" "No Source Available"} {"no regs" "Register Values Unavailable"} }} - {asm asm {{0 0 80 13}} {{0 0 90 26}} + {asm asm {{0 0 80 15}} {{0 0 90 26}} { {"no asm" "No Assembly Available"} }} - {regs asm-regs {{0 0 80 7} {0 6 80 9}} {{0 0 90 13} {0 12 90 13}} + {regs asm-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}} { {"no asm" "No Assembly Available"} {"no regs" "Register Values Unavailable"} }} - {split split {{0 0 80 6} {0 5 80 8}} {{0 0 90 13} {0 12 90 13}} + {split split {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}} { {"no source" "No Source Available"} {"no asm" "No Assembly Available"} }} - {regs split-regs {{0 0 80 6} {0 5 80 8}} {{0 0 90 13} {0 12 90 13}} + {regs split-regs {{0 0 80 8} {0 7 80 8}} {{0 0 90 13} {0 12 90 13}} { {"no asm" "No Assembly Available"} {"no regs" "Register Values Unavailable"} @@ -97,5 +97,9 @@ foreach layout $layouts { check_text $text_list } Term::resize 24 80 + with_test_prefix "80x24 again" { + check_boxes $small_boxes + check_text $text_list + } } } diff --git a/gdb/testsuite/gdb.tui/regs.exp b/gdb/testsuite/gdb.tui/regs.exp index 178eba03f19..2f3482f5d38 100644 --- a/gdb/testsuite/gdb.tui/regs.exp +++ b/gdb/testsuite/gdb.tui/regs.exp @@ -38,8 +38,8 @@ if {![Term::enter_tui]} { Term::check_contents "source at startup" "\\|.*21 *return 0" Term::command "layout regs" -Term::check_box "register box" 0 0 80 7 -Term::check_box "source box in regs layout" 0 6 80 9 +Term::check_box "register box" 0 0 80 8 +Term::check_box "source box in regs layout" 0 7 80 8 set text [Term::get_line 1] # Just check for any register window content at all. diff --git a/gdb/testsuite/gdb.tui/winwidth.exp b/gdb/testsuite/gdb.tui/winwidth.exp index b0a838b578f..1767b25c8d3 100644 --- a/gdb/testsuite/gdb.tui/winwidth.exp +++ b/gdb/testsuite/gdb.tui/winwidth.exp @@ -39,24 +39,25 @@ with_test_prefix "original window sizes" { } with_test_prefix "after src +5" { - Term::check_box "source box" 0 0 44 15 - Term::check_box "asm box" 43 0 37 15 + Term::check_box "source box" 0 0 45 15 + Term::check_box "asm box" 44 0 36 15 Term::command "winwidth asm -5" } with_test_prefix "after asm -5" { - Term::check_box "source box" 0 0 48 15 - Term::check_box "asm box" 47 0 33 15 + Term::dump_screen + Term::check_box "source box" 0 0 50 15 + Term::check_box "asm box" 49 0 31 15 Term::command "winwidth asm +8" } with_test_prefix "after asm +8" { - Term::check_box "source box" 0 0 39 15 - Term::check_box "asm box" 38 0 42 15 + Term::check_box "source box" 0 0 42 15 + Term::check_box "asm box" 41 0 39 15 Term::command "winwidth src -2" } with_test_prefix "after src -2" { - Term::check_box "source box" 0 0 36 15 - Term::check_box "asm box" 35 0 45 15 + Term::check_box "source box" 0 0 40 15 + Term::check_box "asm box" 39 0 41 15 } diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 8758bfe70e7..4988d48a8d5 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -810,11 +810,11 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) info[i].size = info[i].max_size; if (info[i].size < info[i].min_size) info[i].size = info[i].min_size; - /* If there is any leftover size, just redistribute it to the - last resizeable window, by dropping it from the allocated - size. We could try to be fancier here perhaps, by - redistributing this size among all windows, not just the - last window. */ + /* Keep a total of all the size we've used so far (we gain some + size back if this window can share a border with a preceding + window). Any unused space will be distributed between all of + the other windows (while respecting min/max sizes) later in + this function. */ used_size += info[i].size; if (info[i].share_box) --used_size; @@ -834,9 +834,33 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) } /* Allocate any leftover size. */ - if (available_size >= used_size && last_index != -1) + if (available_size > used_size && last_index != -1) { - info[last_index].size += available_size - used_size; + /* Loop over all windows until all available space is used up. */ + bool found_window_that_can_grow_p = true; + for (int idx = last_index; + available_size > used_size; + idx = (idx + 1) % m_splits.size ()) + { + /* Once we have visited all of the windows, check that we did + manage to allocate some more space. This prevents us getting + stuck in the loop forever if we can't allocate anything + more. */ + if (idx == last_index) + { + if (!found_window_that_can_grow_p) + break; + found_window_that_can_grow_p = false; + } + + if (available_size > used_size + && info[idx].size < info[idx].max_size) + { + found_window_that_can_grow_p = true; + info[idx].size += 1; + used_size += 1; + } + } if (debug_tui) { -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (9 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess ` (4 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess When we switch layouts we call the tui_layout_split::apply member function to reapply the layout, and recalculate all the window sizes. One special case is the cmd window, which we try to keep at its existing size. However, in some cases it is not appropriate to keep the cmd window at its existing size. I will describe two such cases here, in one, we want the cmd window to reduce in size, and in the other, we want the cmd window to grow in size. Try these steps in a 80 columns, by 24 lines terminal: (gdb) tui enable (gdb) layout src (gdb) winheight cmd 20 (gdb) layout split You should see that the status window is missing from the new layout, and that the cmd window has been placed over the border of the asm window. The 'info win' output is: (gdb) info win Name Lines Columns Focus src 3 80 (has focus) asm 3 80 status 1 80 cmd 20 80 Notice that gdb has assigned 27 lines of screen space, even with the border overlap between the src and asm windows, this is still 2 lines too many. The problem here is that after switching layouts, gdb has forced the cmd window to retain its 20 line height. Really, we want the cmd window to reduce in height so that the src and asm windows can occupy their minimum required space. This commit allows this (details on how are below). After this commit, in the above situation, we now see the status window displayed correctly, and the 'info win' output is: (gdb) info win Name Lines Columns Focus src 3 80 (has focus) asm 3 80 status 1 80 cmd 18 80 The cmd window has been reduced in size by 2 lines so that everything can fit on the screen. The second example is one which was discussed in a recent commit, consider this case (still in the 80 column, 24 line terminal): (gdb) tui enable (gdb) tui new-layout conly cmd 1 (gdb) layout conly (gdb) info win Name Lines Columns Focus cmd 8 80 (has focus) (gdb) This layout only contains a cmd window, which we would expect to occupy the entire terminal. But instead, the cmd window only occupies the first 8 lines, and the rest of the terminal is unused! The reason is, again, that the cmd window is keeping its previous size (8 lines). After this commit things are slightly different, the 'info win' output is now: (gdb) info win Name Lines Columns Focus cmd 20 80 (has focus) Which is a little better, but why only 20 lines? Turns out there's yet another bug hitting this case. That bug will be addressed in a later commit, so, for now, we're accepting the 20 lines. What this commit does is modify the phase of tui_layout_split::apply that handles any left over space. Usually, in "Step 2", each sub-layout has a size calculated. As the size is an integer, then, when all sizes are calculated we may have some space left over. This extra space is then distributed between all the windows fairly until all the space is used up. When we consider windows minimum size, or fixed size windows, then it is possible that we might try to use more space than is available, this was our first example above. The same code that added extra space to the windows, can also be used to reclaim space (in the over allocation case) to allow all windows to fit. The problem then is the cmd window, which we often force to a fixed size. Inside the loop that handles the allocation of excess space, if we find that we have tried every window, and still have space either left to give, or we need to claim back more space, then, if the cmd window was changed to a fixed size, we can change the cmd window back to a non-fixed-size window, and proceed to either give, or take space from the cmd window as needed. --- gdb/testsuite/gdb.tui/new-layout.exp | 9 +++ gdb/testsuite/gdb.tui/winheight.exp | 46 ++++++++++++++ gdb/tui/tui-layout.c | 95 +++++++++++++++++++++++++--- 3 files changed, 142 insertions(+), 8 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index 66048e65238..0d49d033be5 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -124,5 +124,14 @@ foreach_with_prefix layout $layouts { Term::command "winheight src + 5" Term::check_box "left window box after grow" 0 0 40 15 Term::check_box "right window box after grow" 39 0 41 15 + } elseif {$name == "cmd_only"} { + Term::check_region_contents "bottom of cmd window is blank" \ + 0 14 80 10 "^\\s+$" + Term::command "info win" + Term::check_region_contents "info win output" \ + 0 0 80 24 [multi_line "info win\\s+" \ + "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \ + "cmd\\s+20\\s+80\\s+\\(has focus\\)\\s+" \ + "$gdb_prompt\\s+"] } } diff --git a/gdb/testsuite/gdb.tui/winheight.exp b/gdb/testsuite/gdb.tui/winheight.exp index 0d0c886304d..b541c21b825 100644 --- a/gdb/testsuite/gdb.tui/winheight.exp +++ b/gdb/testsuite/gdb.tui/winheight.exp @@ -50,3 +50,49 @@ Term::check_box "larger source box again" 0 0 80 15 Term::command "layout asm" Term::check_box "check for asm window" 0 0 80 15 + +# Check what happens when we switch from src layout to split layout. +# The interesting thing here is that the src layout has one flexible +# window (the src), the status window, which is of fixed size, and the +# cmd window, which tries to retain its size when a layout changes. +# +# In contrast, the split layout has both a src and asm window, plus +# the same status and cmd windows. +# +# Of particular interest here is the first test, where we maximise the +# cmd window before switching to split. This requires gdb to realise +# that it has to shrink the cmd window, even though this is something +# gdb usually avoids doing. +# +# Each test here is a size for the src window in the 'src' layout. +# The test then switches to the 'split' layout, and calculates the +# expected window sizes. +foreach_with_prefix cmd_size {20 12 5} { + set src_size_before [expr 24 - ${cmd_size} - 1] + set split_size [expr (24 - ${cmd_size}) / 2] + + if { $split_size < 3 } { + # The minimum window size is 3, so force that. + set src_size_after 3 + set asm_size_after 3 + } elseif { [expr $split_size % 2] == 0 } { + # The remaining space can be divided evenly between the two + # windows. + set src_size_after ${split_size} + set asm_size_after ${split_size} + } else { + # The space can't be divided evenly, the asm window will get + # the extra line. + set src_size_after ${split_size} + set asm_size_after [expr ${split_size} + 1] + } + + Term::command "layout src" + Term::command "winheight cmd ${cmd_size}" + Term::check_box "check for src window" 0 0 80 ${src_size_before} + + # Both windows should be of equal size, which will be their minimum. + Term::command "layout split" + Term::check_box "check for src window in split" 0 0 80 ${src_size_after} + Term::check_box "check for asm window in split" 0 [expr ${src_size_after} - 1] 80 ${asm_size_after} +} diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 4988d48a8d5..4742f65f6cf 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -735,6 +735,30 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) width = width_; height = height_; + /* In some situations we fix the size of the cmd window. However, + occasionally this turns out to be a mistake. This struct is used to + hold the original information about the cmd window, so we can restore + it if needed. */ + struct old_size_info + { + /* Constructor. */ + old_size_info (int index_, int min_size_, int max_size_) + : index (index_), + min_size (min_size_), + max_size (max_size_) + { /* Nothing. */ } + + /* The index in m_splits where the cmd window was found. */ + int index; + + /* The previous min/max size. */ + int min_size; + int max_size; + }; + + /* This is given a value only if we fix the size of the cmd window. */ + gdb::optional<old_size_info> old_cmd_info; + std::vector<size_info> info (m_splits.size ()); tui_debug_printf ("weights are: %s", @@ -762,6 +786,10 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) && m_splits[i].layout->get_name () != nullptr && strcmp (m_splits[i].layout->get_name (), "cmd") == 0) { + /* Save the old cmd window information, in case we need to + restore it later. */ + old_cmd_info.emplace (i, info[i].min_size, info[i].max_size); + /* If this layout has never been applied, then it means the user just changed the layout. In this situation, it's desirable to keep the size of the command window the @@ -833,22 +861,66 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) tui_debug_print_size_info (info); } + /* If we didn't find any sub-layouts that were of a non-fixed size, but + we did find the cmd window, then we can consider that a sort-of + non-fixed size sub-layout. + + The cmd window might, initially, be of a fixed size (see above), but, + we are willing to relax this constraint if required to correctly apply + this layout (see below). */ + if (last_index == -1 && old_cmd_info.has_value ()) + last_index = old_cmd_info->index; + /* Allocate any leftover size. */ - if (available_size > used_size && last_index != -1) + if (available_size != used_size && last_index != -1) { - /* Loop over all windows until all available space is used up. */ + /* Loop over all windows until the amount of used space is equal to + the amount of available space. There's an escape hatch within + the loop in case we can't find any sub-layouts to resize. */ bool found_window_that_can_grow_p = true; for (int idx = last_index; - available_size > used_size; + available_size != used_size; idx = (idx + 1) % m_splits.size ()) { - /* Once we have visited all of the windows, check that we did - manage to allocate some more space. This prevents us getting - stuck in the loop forever if we can't allocate anything - more. */ + /* Every time we get back to last_index, which is where the loop + started, we check to make sure that we did assign some space + to a window, bringing used_size closer to available_size. + + If we didn't, but the cmd window is of a fixed size, then we + can make the console window non-fixed-size, and continue + around the loop, hopefully, this will allow the layout to be + applied correctly. + + If we still make it around the loop without moving used_size + closer to available_size, then there's nothing more we can do, + and we break out of the loop. */ if (idx == last_index) { - if (!found_window_that_can_grow_p) + /* If the used_size is greater than the available_size then + this indicates that the fixed-sized sub-layouts claimed + more space than is available. This layout is not going to + work. Our only hope at this point is to make the cmd + window non-fixed-size (if possible), and hope we can + shrink this enough to fit the rest of the sub-layouts in. + + Alternatively, we've made it around the loop without + adjusting any window's size. This likely means all + windows have hit their min or max size. Again, our only + hope is to make the cmd window non-fixed-size, and hope + this fixes all our problems. */ + if (old_cmd_info.has_value () + && ((available_size < used_size) + || !found_window_that_can_grow_p)) + { + info[old_cmd_info->index].min_size = old_cmd_info->min_size; + info[old_cmd_info->index].max_size = old_cmd_info->max_size; + tui_debug_printf + ("restoring index %d (cmd) size limits, min = %d, max = %d", + old_cmd_info->index, old_cmd_info->min_size, + old_cmd_info->max_size); + old_cmd_info.reset (); + } + else if (!found_window_that_can_grow_p) break; found_window_that_can_grow_p = false; } @@ -860,6 +932,13 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) info[idx].size += 1; used_size += 1; } + else if (available_size < used_size + && info[idx].size > info[idx].min_size) + { + found_window_that_can_grow_p = true; + info[idx].size -= 1; + used_size -= 1; + } } if (debug_tui) -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 12/15] gdb/tui: support placing the cmd window into a horizontal layout 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (10 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess ` (3 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit allows the user to place the cmd window within horizontal tui layouts. Consider this set of steps, carried out in an 80 columns by 24 lines terminal, using current master gdb: (gdb) tui new-layout hsrc { -horizontal src 1 cmd 1 } 1 status 1 (gdb) tui layout hsrc What you end up with is a full width cmd window with the status bar beneath. Where's the src window gone? We then try: (gdb) info win Name Lines Columns Focus src 23 3 (has focus) cmd 23 80 status 1 80 (gdb) Something weird has gone on, gdb has overlapped the cmd window with the src window. If we trigger the src window to redraw is content, for example, 'list main', then we see corruption in the cmd window as the src window overwrites it. So, what's going on? The problem is some code in tui_layout_split::apply, in tui-layout.c. Within 'Step 1', there is a loop that calculates the min/max window sizes for all windows within a tui_layout_split. However, there's a special case for the cmd window. This special case is trying to have the cmd window retain its current size when a layout is re-applied, or a new layout is applied. This makes sense, consider moving from the 'src' layout to the 'asm' layout, this looks something like this (status window removed): .-------. .-------. | src | | asm | |-------| ====> |-------| | cmd | | cmd | '-------' '-------' If the user has gone to the effort of adjusting the cmd window size, then, the thinking goes, we shouldn't reset the cmd window size when switching layouts like this. The problem though, is that when we do a switch more like this: .-----------. .-----------. | src | | | | |-----------| ====> | asm | cmd | | cmd | | | | '-----------' '-----------' Now retaining the cmd window width makes no sense; the new layout has a completely different placement for the cmd window, instead of sizing by height, we're now sizing by width. The existing code doesn't understand this though, and tried to retain the full width for the cmd window. To solve this problem, I propose we introduce the idea of a layout "fingerprint". The fingerprint tries to capture, in an abstract way, where the cmd window lives within the layout. Only when two layouts have the same fingerprint will we attempt to retain the cmd window size. The fingerprint for a layout is represented as a string, the string is a series of 'V' or 'H' characters, ending with a single 'C' character. The series of 'V' and 'H' characters represent the vertical or horizontal layouts that must be passed through to find the cmd window. Here are a few examples: # This layout is equivalent to the builtin 'src' layout. # Fingerprint: VC tui new-layout example1 src 2 status 0 cmd 1 # This layout is equivalent to the builtin 'split' layout. # Fingerprint: VC tui new-layout example2 src 1 asm 1 status 0 cmd 1 # This is the same layout that was given at the top. # Fingerprint: VHC tui new-layout hsrc { -horizontal src 1 cmd 1 } 1 status 1 And so, when switching between example1 and example2, gdb knows that the cmd window is, basically, in the same sort of position within the layout, and will retain the cmd window size. In contrast, when switching to the hsrc layout, gdb understands that the position of the cmd window is different, and does not try to retain the cmd window size. --- gdb/testsuite/gdb.tui/new-layout.exp | 5 ++ gdb/tui/tui-layout.c | 69 ++++++++++++++++++++++------ gdb/tui/tui-layout.h | 47 +++++++++++++++---- gdb/tui/tui-win.c | 6 ++- 4 files changed, 102 insertions(+), 25 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index 0d49d033be5..883c7601be7 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -71,6 +71,11 @@ set layouts \ [list h "{-horizontal asm 1 src 1} 1 status 0 cmd 1" \ {{0 0 40 15} {39 0 41 15}} \ "$hex <main>.*21.*return 0"] \ + [list example3 "{-horizontal src 1 cmd 1} 1 status 0 asm 1" \ + {{0 0 40 11} {0 12 80 12}} \ + "21.*return 0.*$hex <main>"] \ + [list example4 "src 1 status 0 {-horizontal cmd 1 regs 1} 1" \ + {{0 0 80 11} {40 12 40 12}} ""] \ [list cmd_only "cmd 1" {} ""]] # Helper function to verify a list of boxes. diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 4742f65f6cf..481a67827f9 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -67,7 +67,7 @@ std::vector<tui_win_info *> tui_windows; /* See tui-layout.h. */ void -tui_apply_current_layout () +tui_apply_current_layout (bool preserve_cmd_win_size_p) { struct gdbarch *gdbarch; CORE_ADDR addr; @@ -77,7 +77,8 @@ tui_apply_current_layout () for (tui_win_info *win_info : tui_windows) win_info->make_visible (false); - applied_layout->apply (0, 0, tui_term_width (), tui_term_height ()); + applied_layout->apply (0, 0, tui_term_width (), tui_term_height (), + preserve_cmd_win_size_p); /* Keep the list of internal windows up-to-date. */ for (int win_type = SRC_WIN; (win_type < MAX_MAJOR_WINDOWS); win_type++) @@ -134,9 +135,18 @@ tui_adjust_window_width (struct tui_win_info *win, int new_width) static void tui_set_layout (tui_layout_split *layout) { + std::string old_fingerprint; + if (applied_layout != nullptr) + old_fingerprint = applied_layout->layout_fingerprint (); + applied_skeleton = layout; applied_layout = layout->clone (); - tui_apply_current_layout (); + + std::string new_fingerprint = applied_layout->layout_fingerprint (); + bool preserve_command_window_size + = (TUI_CMD_WIN != nullptr && old_fingerprint == new_fingerprint); + + tui_apply_current_layout (preserve_command_window_size); } /* See tui-layout.h. */ @@ -158,7 +168,7 @@ tui_add_win_to_layout (enum tui_win_type type) const char *name = type == SRC_WIN ? SRC_NAME : DISASSEM_NAME; applied_layout->replace_window (tui_win_list[other]->name (), name); - tui_apply_current_layout (); + tui_apply_current_layout (true); } /* Find LAYOUT in the "layouts" global and return its index. */ @@ -271,7 +281,7 @@ tui_remove_some_windows () } applied_layout->remove_windows (focus->name ()); - tui_apply_current_layout (); + tui_apply_current_layout (true); } static void @@ -411,7 +421,8 @@ tui_layout_window::clone () const /* See tui-layout.h. */ void -tui_layout_window::apply (int x_, int y_, int width_, int height_) +tui_layout_window::apply (int x_, int y_, int width_, int height_, + bool preserve_cmd_win_size_p) { x = x_; y = y_; @@ -492,6 +503,17 @@ tui_layout_window::specification (ui_file *output, int depth) /* See tui-layout.h. */ +std::string +tui_layout_window::layout_fingerprint () const +{ + if (strcmp (get_name (), "cmd") == 0) + return "C"; + else + return ""; +} + +/* See tui-layout.h. */ + void tui_layout_split::add_split (std::unique_ptr<tui_layout_split> &&layout, int weight) @@ -716,8 +738,11 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p) } else { - /* Simply re-apply the updated layout. */ - apply (x, y, width, height); + /* Simply re-apply the updated layout. We pass false here so that + the cmd window can be resized. However, we should have already + resized everything above to be "just right", so the apply call + here should not end up changing the sizes at all. */ + apply (x, y, width, height, false); } return HANDLED; @@ -726,7 +751,8 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p) /* See tui-layout.h. */ void -tui_layout_split::apply (int x_, int y_, int width_, int height_) +tui_layout_split::apply (int x_, int y_, int width_, int height_, + bool preserve_cmd_win_size_p) { TUI_SCOPED_DEBUG_ENTER_EXIT; @@ -781,7 +807,7 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) m_splits[i].layout->get_sizes (m_vertical, &info[i].min_size, &info[i].max_size); - if (!m_applied + if (preserve_cmd_win_size_p && cmd_win_already_exists && m_splits[i].layout->get_name () != nullptr && strcmp (m_splits[i].layout->get_name (), "cmd") == 0) @@ -964,13 +990,13 @@ tui_layout_split::apply (int x_, int y_, int width_, int height_) else if (info[i].share_box) --size_accum; if (m_vertical) - m_splits[i].layout->apply (x, y + size_accum, width, info[i].size); + m_splits[i].layout->apply (x, y + size_accum, width, info[i].size, + preserve_cmd_win_size_p); else - m_splits[i].layout->apply (x + size_accum, y, info[i].size, height); + m_splits[i].layout->apply (x + size_accum, y, info[i].size, height, + preserve_cmd_win_size_p); size_accum += info[i].size; } - - m_applied = true; } /* See tui-layout.h. */ @@ -1031,6 +1057,21 @@ tui_layout_split::specification (ui_file *output, int depth) fputs_unfiltered ("}", output); } +/* See tui-layout.h. */ + +std::string +tui_layout_split::layout_fingerprint () const +{ + for (auto &item : m_splits) + { + std::string fp = item.layout->layout_fingerprint (); + if (!fp.empty ()) + return std::string (m_vertical ? "V" : "H") + fp; + } + + return ""; +} + /* Destroy the layout associated with SELF. */ static void diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index 9cfcfb8e81f..32bc95171bf 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -55,8 +55,12 @@ class tui_layout_base "skeleton" layout. */ virtual std::unique_ptr<tui_layout_base> clone () const = 0; - /* Change the size and location of this layout. */ - virtual void apply (int x, int y, int width, int height) = 0; + /* Change the size and location of this layout. When + PRESERVE_CMD_WIN_SIZE_P is true the current size of the TUI_CMD_WIN + is preserved, otherwise, the TUI_CMD_WIN will resize just like any + other window. */ + virtual void apply (int x, int y, int width, int height, + bool preserve_cmd_win_size_p) = 0; /* Return the minimum and maximum height or width of this layout. HEIGHT is true to fetch height, false to fetch width. */ @@ -97,6 +101,26 @@ class tui_layout_base depth of this layout in the hierarchy (zero-based). */ virtual void specification (ui_file *output, int depth) = 0; + /* Return a FINGERPRINT string containing an abstract representation of + the location of the cmd window in this layout. + + When called on a complete, top-level layout, the fingerprint will be a + non-empty string made of 'V' and 'H' characters, followed by a single + 'C' character. Each 'V' and 'H' represents a vertical or horizontal + layout that must be passed through in order to find the cmd + window. + + Of course, layouts are built recursively, so, when called on a partial + layout, if this object represents a single window, then either the + empty string is returned (for non-cmd windows), or a string + containing a single 'C' is returned. + + For object representing layouts, if the layout contains the cmd + window then we will get back a valid fingerprint string (contains 'V' + and 'H', ends with 'C'), or, if this layout doesn't contain the cmd + window, an empty string is returned. */ + virtual std::string layout_fingerprint () const = 0; + /* Add all windows to the WINDOWS vector. */ virtual void get_windows (std::vector<tui_win_info *> *windows) = 0; @@ -126,7 +150,8 @@ class tui_layout_window : public tui_layout_base std::unique_ptr<tui_layout_base> clone () const override; - void apply (int x, int y, int width, int height) override; + void apply (int x, int y, int width, int height, + bool preserve_cmd_win_size_p) override; const char *get_name () const override { @@ -155,6 +180,8 @@ class tui_layout_window : public tui_layout_base void specification (ui_file *output, int depth) override; + std::string layout_fingerprint () const override; + /* See tui_layout_base::get_windows. */ void get_windows (std::vector<tui_win_info *> *windows) override { @@ -201,7 +228,8 @@ class tui_layout_split : public tui_layout_base std::unique_ptr<tui_layout_base> clone () const override; - void apply (int x, int y, int width, int height) override; + void apply (int x, int y, int width, int height, + bool preserve_cmd_win_size_p) override; tui_adjust_result set_height (const char *name, int new_height) override { @@ -225,6 +253,8 @@ class tui_layout_split : public tui_layout_base void specification (ui_file *output, int depth) override; + std::string layout_fingerprint () const override; + /* See tui_layout_base::get_windows. */ void get_windows (std::vector<tui_win_info *> *windows) override { @@ -289,9 +319,6 @@ class tui_layout_split : public tui_layout_base /* True if the windows in this split are arranged vertically. */ bool m_vertical; - - /* True if this layout has already been applied at least once. */ - bool m_applied = false; }; /* Add the specified window to the layout in a logical way. This @@ -314,8 +341,10 @@ extern void tui_regs_layout (); some other window is chosen to remain. */ extern void tui_remove_some_windows (); -/* Apply the current layout. */ -extern void tui_apply_current_layout (); +/* Apply the current layout. When PRESERVE_CMD_WIN_SIZE_P is true the + current size of the TUI_CMD_WIN is preserved, otherwise, the TUI_CMD_WIN + will resize just like any other window. */ +extern void tui_apply_current_layout (bool); /* Adjust the window height of WIN to NEW_HEIGHT. */ extern void tui_adjust_window_height (struct tui_win_info *win, diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index 512ea52b694..98dfcc76534 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -511,8 +511,10 @@ tui_resize_all (void) AIX 5.3 does not define clear. */ erase (); clearok (curscr, TRUE); - tui_apply_current_layout (); - /* Turn keypad back on. */ + /* Apply the current layout. The 'false' here allows the command + window to resize proportionately with containing terminal, rather + than maintaining a fixed size. */ + tui_apply_current_layout (false); /* Turn keypad back on. */ keypad (TUI_CMD_WIN->handle.get (), TRUE); } } -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (11 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess ` (2 subsequent siblings) 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit just adds an extra check of the src window size prior to sending all the commands to gdb. We also set the cmd window height to its existing height, this (obviously) shouldn't change the window layout, which we check. My main motivation was adding the initial window layout check, the winheight and recheck are just extras. All of these test pass both before and after this commit. --- gdb/testsuite/gdb.tui/scroll.exp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gdb/testsuite/gdb.tui/scroll.exp b/gdb/testsuite/gdb.tui/scroll.exp index 4eaee0c14ee..c23cd2b9abf 100644 --- a/gdb/testsuite/gdb.tui/scroll.exp +++ b/gdb/testsuite/gdb.tui/scroll.exp @@ -55,6 +55,10 @@ Term::check_region_contents "check cmd window" 0 16 80 8 \ Term::command "tui new-layout flip cmd 1 src 1" Term::command "layout flip" +Term::check_box "src window" 0 8 80 16 +Term::command "winheight cmd 8" +Term::check_box "src window after resize" 0 8 80 16 + for {set i 10} {$i < 20} {incr i 1} { Term::command "p $i" } -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 14/15] gdb/tui: relax restrictions on window max height and width 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (12 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess 2022-03-21 17:52 ` [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess This commit removes some arbitrary adjustments made in tui_cmd_window::max_height, tui_win_info::max_height, and tui_win_info::max_width. These member functions all subtract some constant from the theoretical maximum height or width. I've looked back through the history a little and can see no real reason why these adjustments should be needed, with these adjustments removed all the existing tui tests still pass. However, retaining these restrictions causes some bugs, consider: (gdb) tui new-layout hsrc {-horizontal src 1 cmd 1} 1 When this layout is selected with current master, gdb will leave a 4 line gap at the bottom of the terminal. The problem is that the maximum height is restricted, for the cmd window, to 4 less than the terminal height. By removing this restriction gdb is able to size the windows to the complete terminal height, and the layout is done correctly. This 4 line restriction is also what prevents this layout from working correctly: (gdb) tui new-layout conly cmd 1 Previously, this layout would present a cmd window only, but there would be a 4 line gap at the bottom of the terminal. This issue was mentioned in an earlier commit in this series (when a different bug was fixed), but with this commit, the above layout now correctly fills the terminal. The associated test is updated. After removing the adjustment in tui_cmd_window::max_height, the implementation is now the same as the implementation in the parent class tui_win_info, so I've completely removed the max_height call from tui_cmd_window. --- gdb/testsuite/gdb.tui/new-layout.exp | 4 +++- gdb/tui/tui-command.c | 6 ------ gdb/tui/tui-command.h | 2 -- gdb/tui/tui-win.c | 4 ++-- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index 883c7601be7..e662b1f0b18 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -76,6 +76,8 @@ set layouts \ "21.*return 0.*$hex <main>"] \ [list example4 "src 1 status 0 {-horizontal cmd 1 regs 1} 1" \ {{0 0 80 11} {40 12 40 12}} ""] \ + [list example5 "{-horizontal src 1 cmd 1} 1 status 0" \ + {{0 0 40 23}} ""] \ [list cmd_only "cmd 1" {} ""]] # Helper function to verify a list of boxes. @@ -136,7 +138,7 @@ foreach_with_prefix layout $layouts { Term::check_region_contents "info win output" \ 0 0 80 24 [multi_line "info win\\s+" \ "Name\\s+Lines\\s+Columns\\s+Focus\\s+" \ - "cmd\\s+20\\s+80\\s+\\(has focus\\)\\s+" \ + "cmd\\s+24\\s+80\\s+\\(has focus\\)\\s+" \ "$gdb_prompt\\s+"] } } diff --git a/gdb/tui/tui-command.c b/gdb/tui/tui-command.c index fa8af970b0a..0f6c395f567 100644 --- a/gdb/tui/tui-command.c +++ b/gdb/tui/tui-command.c @@ -31,12 +31,6 @@ /* See tui-command.h. */ -int -tui_cmd_window::max_height () const -{ - return tui_term_height () - 4; -} - void tui_cmd_window::resize (int height_, int width_, int origin_x, int origin_y) { diff --git a/gdb/tui/tui-command.h b/gdb/tui/tui-command.h index 06cc24f6faf..6c354361d1d 100644 --- a/gdb/tui/tui-command.h +++ b/gdb/tui/tui-command.h @@ -31,8 +31,6 @@ struct tui_cmd_window : public tui_win_info DISABLE_COPY_AND_ASSIGN (tui_cmd_window); - int max_height () const override; - void refresh_window () override { } diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index 98dfcc76534..0165fe6c012 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -955,7 +955,7 @@ tui_set_win_width_command (const char *arg, int from_tty) int tui_win_info::max_height () const { - return tui_term_height () - 2; + return tui_term_height (); } /* See tui-data.h. */ @@ -963,7 +963,7 @@ tui_win_info::max_height () const int tui_win_info::max_width () const { - return tui_term_width () - 2; + return tui_term_width (); } static void -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* [PATCHv3 15/15] gdb/tui: fair split of delta after a resize 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (13 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess @ 2022-03-07 22:13 ` Andrew Burgess 2022-03-21 17:52 ` [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess 15 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-03-07 22:13 UTC (permalink / raw) To: gdb-patches; +Cc: Andrew Burgess Currently, in master gdb, when a tui window is changed in size, the screen delta is mostly just added to the next available window. We do take care to respect the min/max size, but in most cases, these limits are just "the terminal size", and so, we end up placing the whole delta on the next window. Consider these steps in an 80 column, 24 line terminal: (gdb) tui enable (gdb) layout src (gdb) layout split (gdb) info win Name Lines Columns Focus src 8 80 (has focus) asm 8 80 status 1 80 cmd 8 80 (gdb) winheight cmd +2 (gdb) info win Name Lines Columns Focus src 6 80 (has focus) asm 8 80 status 1 80 cmd 10 80 Notice that initially, the windows were balanced, 8 lines each for the major windows. Then, when the cmd window was adjusted, the extra two lines were given to the asm window. I think it would be nicer if the delta was spread more evenly over the available windows. In the example above, after the adjustment the layout now looks like: (gdb) info win Name Lines Columns Focus src 7 80 (has focus) asm 7 80 status 1 80 cmd 10 80 This is achieved within tui_layout_split::set_size, by just handing out the delta in increments of 1 to each window (except for the window the user adjusted), until there's no more delta left. Of course, we continue to respect the min/max window sizes. --- gdb/testsuite/gdb.tui/winheight.exp | 31 ++++++++++++++++++++++++ gdb/tui/tui-layout.c | 37 +++++++++++++++++++---------- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/gdb/testsuite/gdb.tui/winheight.exp b/gdb/testsuite/gdb.tui/winheight.exp index b541c21b825..8296dd79513 100644 --- a/gdb/testsuite/gdb.tui/winheight.exp +++ b/gdb/testsuite/gdb.tui/winheight.exp @@ -43,11 +43,42 @@ Term::check_box "smaller source box again" 0 0 80 10 Term::command "winheight src +5" Term::check_box "larger source box again" 0 0 80 15 +# Check that attempting a window to be too large gives an error. +Term::command "winheight src 100" +Term::check_box "source box has not changed" 0 0 80 15 +Term::check_region_contents "check error message about src size 100" 0 16 80 8 \ + [multi_line "$gdb_prompt winheight src 100\\s+" \ + "warning: Invalid window height specified\\s+" \ + "$gdb_prompt"] + +# Check that incrementing to a size that is "too big" will trigger an +# error, and that the window doesn't resize. +Term::command "winheight src 20" +Term::check_box "source box is at its max size" 0 0 80 20 +Term::command "winheight src +1" +Term::check_box "source box is still at its max size" 0 0 80 20 +Term::check_region_contents "check error message about src +1" 0 21 80 3 \ + [multi_line "$gdb_prompt winheight src \\+1\\s+" \ + "warning: Invalid window height specified\\s+" \ + "$gdb_prompt"] + +# Reset the cmd window to a sane size. +Term::command "winheight cmd 8" + +Term::command "layout regs" +Term::check_box "register window" 0 0 80 8 +Term::check_box "source window" 0 7 80 8 + +Term::command "winheight cmd 10" +Term::check_box "register window after resize" 0 0 80 7 +Term::check_box "source window after resize" 0 6 80 7 + # At one point we had a bug where adjusting the winheight would result # in GDB keeping hold of duplicate window pointers, which it might # then try to delete when the layout was changed. Running this test # under valgrind would expose that bug. Term::command "layout asm" +Term::command "winheight cmd 8" Term::check_box "check for asm window" 0 0 80 15 diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 481a67827f9..a40d2181968 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -691,12 +691,21 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p) tui_debug_printf ("before delta (%d) distribution, weights: %s", delta, tui_debug_weights_to_string ().c_str ()); - /* Distribute the "delta" over the next window; but if the next - window cannot hold it all, keep going until we either find a - window that does, or until we loop all the way around. */ - for (int i = 0; delta != 0 && i < m_splits.size () - 1; ++i) + /* Distribute the "delta" over all other windows, while respecting their + min/max sizes. We grow each window by 1 line at a time continually + looping over all the windows. However, skip the window that the user + just resized, obviously we don't want to readjust that window. */ + bool found_window_that_can_grow_p = true; + for (int i = 0; delta != 0; i = (i + 1) % m_splits.size ()) { int index = (found_index + 1 + i) % m_splits.size (); + if (index == found_index) + { + if (!found_window_that_can_grow_p) + break; + found_window_that_can_grow_p = false; + continue; + } int new_min, new_max; m_splits[index].layout->get_sizes (m_vertical, &new_min, &new_max); @@ -705,19 +714,23 @@ tui_layout_split::set_size (const char *name, int new_size, bool set_width_p) { /* The primary window grew, so we are trying to shrink other windows. */ - int available = m_splits[index].weight - new_min; - int shrink_by = std::min (available, -delta); - m_splits[index].weight -= shrink_by; - delta += shrink_by; + if (m_splits[index].weight > new_min) + { + m_splits[index].weight -= 1; + delta += 1; + found_window_that_can_grow_p = true; + } } else { /* The primary window shrank, so we are trying to grow other windows. */ - int available = new_max - m_splits[index].weight; - int grow_by = std::min (available, delta); - m_splits[index].weight += grow_by; - delta -= grow_by; + if (m_splits[index].weight < new_max) + { + m_splits[index].weight += 1; + delta -= 1; + found_window_that_can_grow_p = true; + } } tui_debug_printf ("index = %d, weight now: %d", -- 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess ` (14 preceding siblings ...) 2022-03-07 22:13 ` [PATCHv3 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess @ 2022-03-21 17:52 ` Andrew Burgess 2022-03-30 9:13 ` Andrew Burgess 15 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-03-21 17:52 UTC (permalink / raw) To: gdb-patches Ping! Thanks, Andrew Andrew Burgess <aburgess@redhat.com> writes: > Since v2: > > - Rebased onto current upstream/master, > > - Patch #5 - Rewritten to not use templates! > > - Patch #6 - Added a bug in bugzilla, and referenced this from the > commit message, > > - Patch #7 - Renamed the existing methods rather than adding 2 new > methods, > > - Patch #10 - Updated the comment Tom identified as being out of > date, > > - Patch #15 - Have updated a comment that I spotted was out of date. > > Thanks, > Andrew > > > --- > > Andrew Burgess (15): > gdb: move some commands into the tui namespace > gdb/tui: rename tui_layout_base::adjust_size to ::set_height > gdb/tui: rename tui_layout_split:set_weights_from_heights > gdb/testing/tui: add new functionality to tuiterm.exp > gdb/tui: add new 'tui window width' command and 'winwidth' alias > gdb/tui: add a tui debugging flag > gdb/tui: add left_boxed_p and right_boxed_p member functions > gdb/tui/testsuite: refactor new-layout.exp test > gdb/tui: avoid fp exception when applying layouts > gdb/tui: fairer distribution of excess space during apply > gdb/tui: allow cmd window to change size in tui_layout_split::apply > gdb/tui: support placing the cmd window into a horizontal layout > gdb/testsuite: some additional tests in gdb.tui/scroll.exp > gdb/tui: relax restrictions on window max height and width > gdb/tui: fair split of delta after a resize > > gdb/NEWS | 25 ++ > gdb/doc/gdb.texinfo | 51 +++- > gdb/testsuite/gdb.tui/basic.exp | 4 +- > gdb/testsuite/gdb.tui/empty.exp | 14 +- > gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++-- > gdb/testsuite/gdb.tui/regs.exp | 4 +- > gdb/testsuite/gdb.tui/scroll.exp | 4 + > gdb/testsuite/gdb.tui/winheight.exp | 77 +++++ > gdb/testsuite/gdb.tui/winwidth.exp | 63 +++++ > gdb/testsuite/lib/tuiterm.exp | 82 +++++- > gdb/tui/tui-command.c | 6 - > gdb/tui/tui-command.h | 2 - > gdb/tui/tui-layout.c | 406 ++++++++++++++++++++++----- > gdb/tui/tui-layout.h | 135 +++++++-- > gdb/tui/tui-win.c | 118 ++++++-- > gdb/tui/tui.c | 26 ++ > gdb/tui/tui.h | 14 + > 17 files changed, 971 insertions(+), 160 deletions(-) > create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp > > -- > 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes 2022-03-21 17:52 ` [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess @ 2022-03-30 9:13 ` Andrew Burgess 2022-04-03 14:43 ` Andrew Burgess 0 siblings, 1 reply; 74+ messages in thread From: Andrew Burgess @ 2022-03-30 9:13 UTC (permalink / raw) To: gdb-patches I'm planning to push this series soon(ish) unless someone complains. The only series comments on v2 were for patch #5, which I believe are now addressed. As always, if there's any feedback post-commit, I'm happy to address issues as they are raised. Thanks, Andrew Andrew Burgess <aburgess@redhat.com> writes: > Ping! > > Thanks, > Andrew > > > Andrew Burgess <aburgess@redhat.com> writes: > >> Since v2: >> >> - Rebased onto current upstream/master, >> >> - Patch #5 - Rewritten to not use templates! >> >> - Patch #6 - Added a bug in bugzilla, and referenced this from the >> commit message, >> >> - Patch #7 - Renamed the existing methods rather than adding 2 new >> methods, >> >> - Patch #10 - Updated the comment Tom identified as being out of >> date, >> >> - Patch #15 - Have updated a comment that I spotted was out of date. >> >> Thanks, >> Andrew >> >> >> --- >> >> Andrew Burgess (15): >> gdb: move some commands into the tui namespace >> gdb/tui: rename tui_layout_base::adjust_size to ::set_height >> gdb/tui: rename tui_layout_split:set_weights_from_heights >> gdb/testing/tui: add new functionality to tuiterm.exp >> gdb/tui: add new 'tui window width' command and 'winwidth' alias >> gdb/tui: add a tui debugging flag >> gdb/tui: add left_boxed_p and right_boxed_p member functions >> gdb/tui/testsuite: refactor new-layout.exp test >> gdb/tui: avoid fp exception when applying layouts >> gdb/tui: fairer distribution of excess space during apply >> gdb/tui: allow cmd window to change size in tui_layout_split::apply >> gdb/tui: support placing the cmd window into a horizontal layout >> gdb/testsuite: some additional tests in gdb.tui/scroll.exp >> gdb/tui: relax restrictions on window max height and width >> gdb/tui: fair split of delta after a resize >> >> gdb/NEWS | 25 ++ >> gdb/doc/gdb.texinfo | 51 +++- >> gdb/testsuite/gdb.tui/basic.exp | 4 +- >> gdb/testsuite/gdb.tui/empty.exp | 14 +- >> gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++-- >> gdb/testsuite/gdb.tui/regs.exp | 4 +- >> gdb/testsuite/gdb.tui/scroll.exp | 4 + >> gdb/testsuite/gdb.tui/winheight.exp | 77 +++++ >> gdb/testsuite/gdb.tui/winwidth.exp | 63 +++++ >> gdb/testsuite/lib/tuiterm.exp | 82 +++++- >> gdb/tui/tui-command.c | 6 - >> gdb/tui/tui-command.h | 2 - >> gdb/tui/tui-layout.c | 406 ++++++++++++++++++++++----- >> gdb/tui/tui-layout.h | 135 +++++++-- >> gdb/tui/tui-win.c | 118 ++++++-- >> gdb/tui/tui.c | 26 ++ >> gdb/tui/tui.h | 14 + >> 17 files changed, 971 insertions(+), 160 deletions(-) >> create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp >> >> -- >> 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes 2022-03-30 9:13 ` Andrew Burgess @ 2022-04-03 14:43 ` Andrew Burgess 0 siblings, 0 replies; 74+ messages in thread From: Andrew Burgess @ 2022-04-03 14:43 UTC (permalink / raw) To: gdb-patches Andrew Burgess <aburgess@redhat.com> writes: > I'm planning to push this series soon(ish) unless someone complains. I've now pushed this series. Thanks, Andrew > > The only series comments on v2 were for patch #5, which I believe are > now addressed. > > As always, if there's any feedback post-commit, I'm happy to address > issues as they are raised. > > Thanks, > Andrew > > > Andrew Burgess <aburgess@redhat.com> writes: > >> Ping! >> >> Thanks, >> Andrew >> >> >> Andrew Burgess <aburgess@redhat.com> writes: >> >>> Since v2: >>> >>> - Rebased onto current upstream/master, >>> >>> - Patch #5 - Rewritten to not use templates! >>> >>> - Patch #6 - Added a bug in bugzilla, and referenced this from the >>> commit message, >>> >>> - Patch #7 - Renamed the existing methods rather than adding 2 new >>> methods, >>> >>> - Patch #10 - Updated the comment Tom identified as being out of >>> date, >>> >>> - Patch #15 - Have updated a comment that I spotted was out of date. >>> >>> Thanks, >>> Andrew >>> >>> >>> --- >>> >>> Andrew Burgess (15): >>> gdb: move some commands into the tui namespace >>> gdb/tui: rename tui_layout_base::adjust_size to ::set_height >>> gdb/tui: rename tui_layout_split:set_weights_from_heights >>> gdb/testing/tui: add new functionality to tuiterm.exp >>> gdb/tui: add new 'tui window width' command and 'winwidth' alias >>> gdb/tui: add a tui debugging flag >>> gdb/tui: add left_boxed_p and right_boxed_p member functions >>> gdb/tui/testsuite: refactor new-layout.exp test >>> gdb/tui: avoid fp exception when applying layouts >>> gdb/tui: fairer distribution of excess space during apply >>> gdb/tui: allow cmd window to change size in tui_layout_split::apply >>> gdb/tui: support placing the cmd window into a horizontal layout >>> gdb/testsuite: some additional tests in gdb.tui/scroll.exp >>> gdb/tui: relax restrictions on window max height and width >>> gdb/tui: fair split of delta after a resize >>> >>> gdb/NEWS | 25 ++ >>> gdb/doc/gdb.texinfo | 51 +++- >>> gdb/testsuite/gdb.tui/basic.exp | 4 +- >>> gdb/testsuite/gdb.tui/empty.exp | 14 +- >>> gdb/testsuite/gdb.tui/new-layout.exp | 100 +++++-- >>> gdb/testsuite/gdb.tui/regs.exp | 4 +- >>> gdb/testsuite/gdb.tui/scroll.exp | 4 + >>> gdb/testsuite/gdb.tui/winheight.exp | 77 +++++ >>> gdb/testsuite/gdb.tui/winwidth.exp | 63 +++++ >>> gdb/testsuite/lib/tuiterm.exp | 82 +++++- >>> gdb/tui/tui-command.c | 6 - >>> gdb/tui/tui-command.h | 2 - >>> gdb/tui/tui-layout.c | 406 ++++++++++++++++++++++----- >>> gdb/tui/tui-layout.h | 135 +++++++-- >>> gdb/tui/tui-win.c | 118 ++++++-- >>> gdb/tui/tui.c | 26 ++ >>> gdb/tui/tui.h | 14 + >>> 17 files changed, 971 insertions(+), 160 deletions(-) >>> create mode 100644 gdb/testsuite/gdb.tui/winwidth.exp >>> >>> -- >>> 2.25.4 ^ permalink raw reply [flat|nested] 74+ messages in thread
* Re: [PATCH 0/7] TUI command changes, including new winwidth command 2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess ` (7 preceding siblings ...) 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess @ 2022-03-04 17:23 ` Tom Tromey 8 siblings, 0 replies; 74+ messages in thread From: Tom Tromey @ 2022-03-04 17:23 UTC (permalink / raw) To: Andrew Burgess via Gdb-patches; +Cc: Andrew Burgess >>>>> "Andrew" == Andrew Burgess via Gdb-patches <gdb-patches@sourceware.org> writes: Andrew> I'm working on a patch to improve the TUI's window sizing and resizing Andrew> behaviour. That's still a work in progress. But, as part of that Andrew> work I needed to add support for resizing the width of a window. Andrew> Given that we have horizontal window layout support, I think it makes Andrew> sense to have this functionality whether or not I finish my bigger Andrew> window resizing work. I sent some notes, but nothing serious. I think it looks great overall, though I did also have the same question as Pedro for patch #5. Tom ^ permalink raw reply [flat|nested] 74+ messages in thread
end of thread, other threads:[~2022-04-03 14:43 UTC | newest] Thread overview: 74+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-01-28 15:55 [PATCH 0/7] TUI command changes, including new winwidth command Andrew Burgess 2022-01-28 15:55 ` [PATCH 1/7] gdb/tui: add window width information to 'info win' output Andrew Burgess 2022-01-28 17:00 ` Eli Zaretskii 2022-02-06 13:43 ` Andrew Burgess 2022-01-28 15:55 ` [PATCH 2/7] gdb/doc: update docs for 'info win' and 'winheight' commands Andrew Burgess 2022-01-28 17:03 ` Eli Zaretskii 2022-02-06 13:43 ` Andrew Burgess 2022-01-28 15:55 ` [PATCH 3/7] gdb: move some commands into the tui namespace Andrew Burgess 2022-01-28 17:04 ` Eli Zaretskii 2022-01-28 15:55 ` [PATCH 4/7] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess 2022-01-28 15:55 ` [PATCH 5/7] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess 2022-01-28 15:55 ` [PATCH 6/7] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess 2022-01-28 15:55 ` [PATCH 7/7] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess 2022-01-28 17:05 ` Eli Zaretskii 2022-02-06 14:12 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 01/15] gdb: move some commands into the tui namespace Andrew Burgess 2022-02-06 15:50 ` Eli Zaretskii 2022-02-06 14:12 ` [PATCHv2 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess 2022-03-04 16:29 ` Tom Tromey 2022-02-06 14:12 ` [PATCHv2 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess 2022-02-06 15:52 ` Eli Zaretskii 2022-02-09 15:33 ` Andrew Burgess 2022-02-09 17:03 ` Eli Zaretskii 2022-03-03 18:52 ` Pedro Alves 2022-02-06 14:12 ` [PATCHv2 06/15] gdb/tui: add a tui debugging flag Andrew Burgess 2022-02-06 15:53 ` Eli Zaretskii 2022-03-04 16:35 ` Tom Tromey 2022-02-06 14:12 ` [PATCHv2 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess 2022-03-04 16:37 ` Tom Tromey 2022-02-06 14:12 ` [PATCHv2 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess 2022-03-04 16:42 ` Tom Tromey 2022-02-06 14:12 ` [PATCHv2 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess 2022-03-04 17:17 ` Tom Tromey 2022-03-07 20:05 ` Andrew Burgess 2022-03-07 21:24 ` Tom Tromey 2022-02-06 14:12 ` [PATCHv2 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess 2022-03-04 17:20 ` Tom Tromey 2022-03-07 20:08 ` Andrew Burgess 2022-02-06 14:12 ` [PATCHv2 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess 2022-03-04 17:22 ` Tom Tromey 2022-03-07 22:07 ` Andrew Burgess 2022-03-07 23:42 ` Tom Tromey 2022-02-21 17:29 ` [PATCHv2 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess 2022-03-02 17:59 ` Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 " Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 01/15] gdb: move some commands into the tui namespace Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 02/15] gdb/tui: rename tui_layout_base::adjust_size to ::set_height Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 03/15] gdb/tui: rename tui_layout_split:set_weights_from_heights Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 04/15] gdb/testing/tui: add new functionality to tuiterm.exp Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 05/15] gdb/tui: add new 'tui window width' command and 'winwidth' alias Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 06/15] gdb/tui: add a tui debugging flag Andrew Burgess 2022-03-08 12:16 ` Eli Zaretskii 2022-03-09 11:48 ` Andrew Burgess 2022-03-09 12:58 ` Eli Zaretskii 2022-03-09 17:53 ` Tom Tromey 2022-03-07 22:13 ` [PATCHv3 07/15] gdb/tui: add left_boxed_p and right_boxed_p member functions Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 08/15] gdb/tui/testsuite: refactor new-layout.exp test Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 09/15] gdb/tui: avoid fp exception when applying layouts Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 10/15] gdb/tui: fairer distribution of excess space during apply Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 11/15] gdb/tui: allow cmd window to change size in tui_layout_split::apply Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 12/15] gdb/tui: support placing the cmd window into a horizontal layout Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 13/15] gdb/testsuite: some additional tests in gdb.tui/scroll.exp Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 14/15] gdb/tui: relax restrictions on window max height and width Andrew Burgess 2022-03-07 22:13 ` [PATCHv3 15/15] gdb/tui: fair split of delta after a resize Andrew Burgess 2022-03-21 17:52 ` [PATCHv3 00/15] TUI changes, new winwidth command and resizing changes Andrew Burgess 2022-03-30 9:13 ` Andrew Burgess 2022-04-03 14:43 ` Andrew Burgess 2022-03-04 17:23 ` [PATCH 0/7] TUI command changes, including new winwidth command Tom Tromey
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).