[PATCH] ui/ncurses: Improve update handling in nested screens

Samuel Mendoza-Jonas sam.mj at au1.ibm.com
Thu Sep 3 16:50:58 AEST 2015


Several screens in petitboot-nc require an update if a config or sysinfo
update is received. However if those screens exist but are not the
current screen they will incorrectly try to draw to the screen.

Where the currently active screen is a textscreen (eg. a help screen)
the update is delayed until after the screen is exited.

In the particular case of nc-config where the current screen can be an
nc-subset screen, the nc-subset screen is exited immediately so the
update can be performed, since the nc-subset screen depends on the
information in the previous screen.

Signed-off-by: Samuel Mendoza-Jonas <sam.mj at au1.ibm.com>
---
 ui/ncurses/nc-boot-editor.c | 16 +++++++++++++++-
 ui/ncurses/nc-config.c      | 45 ++++++++++++++++++++++++++++++---------------
 ui/ncurses/nc-cui.c         |  6 ++++++
 ui/ncurses/nc-subset.c      |  6 ++++++
 ui/ncurses/nc-sysinfo.c     |  6 +++++-
 ui/ncurses/nc-textscreen.c  |  8 ++++++++
 ui/ncurses/nc-textscreen.h  |  1 +
 7 files changed, 71 insertions(+), 17 deletions(-)

diff --git a/ui/ncurses/nc-boot-editor.c b/ui/ncurses/nc-boot-editor.c
index f55fe4a..b57ccf8 100644
--- a/ui/ncurses/nc-boot-editor.c
+++ b/ui/ncurses/nc-boot-editor.c
@@ -44,6 +44,7 @@ struct boot_editor {
 					struct pmenu_item *item,
 					struct pb_boot_data *bd);
 	bool			need_redraw;
+	bool			need_update;
 
 	int			label_x;
 	int			field_x;
@@ -109,7 +110,14 @@ static struct boot_editor *boot_editor_from_arg(void *arg)
 static int boot_editor_post(struct nc_scr *scr)
 {
 	struct boot_editor *boot_editor = boot_editor_from_scr(scr);
-	widgetset_post(boot_editor->widgetset);
+
+	if (boot_editor->need_update) {
+		boot_editor_update(boot_editor, boot_editor->cui->sysinfo);
+		boot_editor->need_update = false;
+	} else {
+		widgetset_post(boot_editor->widgetset);
+	}
+
 	nc_scr_frame_draw(scr);
 	if (boot_editor->need_redraw) {
 		redrawwin(scr->main_ncw);
@@ -503,6 +511,11 @@ void boot_editor_update(struct boot_editor *boot_editor,
 {
 	int height;
 
+	if (boot_editor->cui->current != boot_editor_scr(boot_editor)) {
+		boot_editor->need_update = true;
+		return;
+	}
+
 	widgetset_unpost(boot_editor->widgetset);
 
 	height = pad_height(sysinfo ? sysinfo->n_blockdevs : 0);
@@ -543,6 +556,7 @@ struct boot_editor *boot_editor_init(struct cui *cui,
 	boot_editor->on_exit = on_exit;
 	boot_editor->state = STATE_EDIT;
 	boot_editor->need_redraw = false;
+	boot_editor->need_update = false;
 
 	int ncols1 = strncols(_("Device tree:"));
 	int ncols2 = strncols(_("Boot arguments:"));
diff --git a/ui/ncurses/nc-config.c b/ui/ncurses/nc-config.c
index f7c6b8c..7a4d22e 100644
--- a/ui/ncurses/nc-config.c
+++ b/ui/ncurses/nc-config.c
@@ -53,6 +53,7 @@ struct config_screen {
 	bool			show_help;
 	bool			show_subset;
 	bool			need_redraw;
+	bool			need_update;
 
 	void			(*on_exit)(struct cui *);
 
@@ -170,21 +171,6 @@ static void config_screen_resize(struct nc_scr *scr)
 	(void)screen;
 }
 
-static int config_screen_post(struct nc_scr *scr)
-{
-	struct config_screen *screen = config_screen_from_scr(scr);
-	screen->show_subset = false;
-	widgetset_post(screen->widgetset);
-	nc_scr_frame_draw(scr);
-	if (screen->need_redraw) {
-		redrawwin(scr->main_ncw);
-		screen->need_redraw = false;
-	}
-	wrefresh(screen->scr.main_ncw);
-	pad_refresh(screen);
-	return 0;
-}
-
 static int config_screen_unpost(struct nc_scr *scr)
 {
 	struct config_screen *screen = config_screen_from_scr(scr);
@@ -1009,10 +995,38 @@ void config_screen_update(struct config_screen *screen,
 		const struct config *config,
 		const struct system_info *sysinfo)
 {
+	if (screen->cui->current != config_screen_scr(screen)) {
+		screen->need_update = true;
+		return;
+	}
+
 	config_screen_draw(screen, config, sysinfo);
 	pad_refresh(screen);
 }
 
+static int config_screen_post(struct nc_scr *scr)
+{
+	struct config_screen *screen = config_screen_from_scr(scr);
+	screen->show_subset = false;
+
+	if (screen->need_update) {
+		config_screen_draw(screen, screen->cui->config,
+				   screen->cui->sysinfo);
+		screen->need_update = false;
+	} else {
+		widgetset_post(screen->widgetset);
+	}
+
+	nc_scr_frame_draw(scr);
+	if (screen->need_redraw) {
+		redrawwin(scr->main_ncw);
+		screen->need_redraw = false;
+	}
+	wrefresh(screen->scr.main_ncw);
+	pad_refresh(screen);
+	return 0;
+}
+
 static int config_screen_destroy(void *arg)
 {
 	struct config_screen *screen = arg;
@@ -1038,6 +1052,7 @@ struct config_screen *config_screen_init(struct cui *cui,
 	screen->cui = cui;
 	screen->on_exit = on_exit;
 	screen->need_redraw = false;
+	screen->need_update = false;
 	screen->label_x = 2;
 	screen->field_x = 17;
 
diff --git a/ui/ncurses/nc-cui.c b/ui/ncurses/nc-cui.c
index 56e7653..c975c0f 100644
--- a/ui/ncurses/nc-cui.c
+++ b/ui/ncurses/nc-cui.c
@@ -698,6 +698,9 @@ static void cui_update_sysinfo(struct system_info *sysinfo, void *arg)
 	if (cui->sysinfo_screen)
 		sysinfo_screen_update(cui->sysinfo_screen, sysinfo);
 
+	if (cui->subset_screen)
+		subset_screen_update(cui->subset_screen);
+
 	/* ... and do the same with the config screen... */
 	if (cui->config_screen)
 		config_screen_update(cui->config_screen, cui->config, sysinfo);
@@ -744,6 +747,9 @@ static void cui_update_config(struct config *config, void *arg)
 	if (config->lang)
 		cui_update_language(cui, config->lang);
 
+	if (cui->subset_screen)
+		subset_screen_update(cui->subset_screen);
+
 	if (cui->config_screen)
 		config_screen_update(cui->config_screen, config, cui->sysinfo);
 
diff --git a/ui/ncurses/nc-subset.c b/ui/ncurses/nc-subset.c
index f38e394..0faed3b 100644
--- a/ui/ncurses/nc-subset.c
+++ b/ui/ncurses/nc-subset.c
@@ -62,6 +62,12 @@ struct nc_scr *subset_screen_return_scr(struct subset_screen *screen)
 	return screen->return_scr;
 }
 
+void subset_screen_update(struct subset_screen *screen)
+{
+	pb_debug("Exiting subset due to update\n");
+	return screen->on_exit(screen->cui);
+}
+
 static struct subset_screen *subset_screen_from_scr(struct nc_scr *scr)
 {
 	struct subset_screen *subset_screen;
diff --git a/ui/ncurses/nc-sysinfo.c b/ui/ncurses/nc-sysinfo.c
index bde8b33..ac8ece7 100644
--- a/ui/ncurses/nc-sysinfo.c
+++ b/ui/ncurses/nc-sysinfo.c
@@ -104,7 +104,11 @@ void sysinfo_screen_update(struct sysinfo_screen *screen,
 		const struct system_info *sysinfo)
 {
 	sysinfo_screen_populate(screen, sysinfo);
-	text_screen_draw(&screen->text_scr);
+
+	if (screen->text_scr.cui->help_screen)
+		screen->text_scr.need_update = true;
+	else
+		text_screen_draw(&screen->text_scr);
 }
 
 struct sysinfo_screen *sysinfo_screen_init(struct cui *cui,
diff --git a/ui/ncurses/nc-textscreen.c b/ui/ncurses/nc-textscreen.c
index 826244c..55428e7 100644
--- a/ui/ncurses/nc-textscreen.c
+++ b/ui/ncurses/nc-textscreen.c
@@ -183,6 +183,13 @@ void text_screen_set_help(struct text_screen *screen, const char *title,
 
 static int text_screen_post(struct nc_scr *scr)
 {
+	struct text_screen *screen = text_screen_from_scr(scr);
+
+	if (screen->need_update) {
+		text_screen_draw(screen);
+		screen->need_update = false;
+	}
+
 	nc_scr_frame_draw(scr);
 	redrawwin(scr->main_ncw);
 	wrefresh(scr->main_ncw);
@@ -202,6 +209,7 @@ void text_screen_init(struct text_screen *screen, struct cui *cui,
 
 	screen->cui = cui;
 	screen->on_exit = on_exit;
+	screen->need_update = false;
 
 	screen->scr.frame.ltitle = talloc_strdup(screen, title);
 	screen->scr.frame.rtitle = NULL;
diff --git a/ui/ncurses/nc-textscreen.h b/ui/ncurses/nc-textscreen.h
index 25107cb..df47186 100644
--- a/ui/ncurses/nc-textscreen.h
+++ b/ui/ncurses/nc-textscreen.h
@@ -28,6 +28,7 @@ struct text_screen {
 	int			n_lines;
 	int			n_alloc_lines;
 	int			scroll_y;
+	bool			need_update;
 	const char		*help_title;
 	const struct help_text	*help_text;
 	void			(*on_exit)(struct cui *);
-- 
2.5.0



More information about the Petitboot mailing list