Sandbox application framework

Function sndbx_nav_page_get_prev() is the same as sndbx_nav_page_get_prev(), both init from node with the same direction(LIST_HEAD), is that right?

parent is the object/containter/page/screen in which the content is placed. In the case of sndbx_app_monolith.c it is used in settings_cb, info_cb and help_cb to open dialog items when the respective buttons are pressed. In sndbx_app_test.c it is not really needed, I left that there as a stub in case at some point settings/help/info are added.

Yes. sndbx_nav_page_get_prev() returns previous and sndbx_nav_page_get_next() returns next from the same node (page).

Thank you for the answer.

Some pages have destroy_cb, some don’t, what’s the reason behind it? Another question, is it possible to change to a different page from one page after certain idle time(no input) for the frame work?

This is an optional in case your page (in create or task for example) allocates or instantiates other resources (memory for example) or lvgl tasks that are not specifically managed by the framework. Before changing to a new page, the framework will call the destroy callback if it exists as part of the cleanup process. If it is not needed then no need to specify it (the pointer) in the descriptor, or it can be specifically set to NULL.
Have a look at sndbx_pge_demo.c for a typical example on how it would be used.

You could do this by having a timed process. For example initialise a counter in create_cb and count it down in task_cb and when it expires then change the page using sndbx_pge_change(new_page), where new_page is the pointer to the new page descriptor.

I see. If need to switch to a different page after being idle for a while, need to set timer in device input functions. Thank you.

Updated for LVGL release/v7 branch.
Still uses SDL, I will try to change it to use win32drv in the near future, but it works for now.

I eventually got round to working on this framework again and have upgraded it to work with LVGL V8.3.1,
I have tested it on the Visual Studio Simulator repo ( ) but see no reason why it would not work elsewhere.

ALL LVGL demo apps and example apps are available with a single compilation (no need for constant recompilation to test any of the LVGL demos and example snippets) as long as their dependencies are correctly set in lv_conf.h, 155 apps in total unless I added them up incorrectly.

For most of the LVGL apps, my app sndbx_pge_lvgl_apps_test() once compiled to an executable and running will let you navigate to them, run them and then navigate backwards out of them, in this way you are able to iteratively try them out. There are exceptions for those that start timers - All the demo apps,
lv_demo_benchmark(), lv_demo_ music(), lv_demo_stress(), lv_demo_widgets() as well as lv_demo_keypad_encoder(), and specific Widget examples lv_example_event_4(), lv_example_chart_2(), lv_example_chart_7(), lv_example_chart_9()
These can all still be navigated to and run, but once they are running you cannot navigate back. You will need to close and restart the application.

To use my app and sandbox framework,

  • Download the zip file below
  • Unzip it next to the lvgl directory (See screenshot)
  • Add #include "sndbx/pages/sndbx_pges.h" to LVGL.Simulator.cpp or main.c as it may be in your case
  • Call sndbx_pge_lvgl_apps_test() from main() as you would a demo or example app.
  • Compile and run, (See screenshot).


If you want Examples alone, call sndbx_pge_lv_examples_test() instead,

If you want Examples > Widgets alone, call sndbx_pge_lv_ex_widgets_test() instead,
On Examples > Widgets, the list button on the top right will toggle light and dark mode if LV_USE_THEME_DEFAULT is defined as non 0 in lv_conf.h (42.8 KB)

I hope some people find this useful, I use this framework for just about all of my LVGL projects, as it gives me a consistent look and feel and familiar “web page” like user experience.

Any feedback is welcome.

After testing on a Raspberry Pi with the official 7’ touch display, I found that the back and forward navigation buttons were not being shown in the header.
Commenting line 767 out in sndbx.c, lv_obj_set_width(btn, lv_obj_get_height(par)*3/2); or (for wider buttons as originally intended) changing it to lv_obj_set_width(btn, LV_VER_RES/10*3/2); fixed the problem.

My project uses LVGL v.8.3 and FreeRTOS.
It is planned to use a large number of screens. For this reason, I wanted to try using your achievements as a sandbox application. To do this, I downloaded the archive from the link you provided. When compiling your code, errors occurred due to the fact that the list.c and list.h files are already involved and used in FreeRTOS. For this reason, I had to change the names of these two files. Along the way, I had to edit the names of some functions, because they changed in LVGL 8.3.
Then I tried to use the code from your message: A few of my projects - #7 by deonm
But it doesn’t work because it’s written under LVG v.7.x
Could you give minimal examples for LVGL v.8.x?


I will have a look and post something in line with what you asked.

In the meantime, I also come across the same issue regarding file names list.c and list.h when using the framework with FreeRTOS. There are a few ways to resolve this, but one way is merely to create sndbx_list.c and sndbx_list.h and to have #include statements. ie #include "list.c" and #include "list.h" in the respective two files. Obviously the project needs to be set up to compile sndbx_list.c and not list.c (referring to list.c used by sandbox, not the one used by FreeRTOS).

Simple status area code, tested on v8.3.4

typedef struct {
	lv_obj_t * hdr;
	lv_obj_t * btn;
	lv_obj_t * lbl;
	char * buf;
	size_t buf_size;
} htd_t;

static void header_task( struct _lv_timer_t * tmr )
	htd_t * mem = tmr->user_data;
	if( !mem )
	time_t tme = time(NULL);
	time_t tme1 = tme;
	tme /= 60;
	unsigned mm = tme%60;
	unsigned hh = (tme%1440)/60;

	sprintf( mem->buf, tme1&1 ? "%.2u %.2u" : "%.2u:%.2u"
		, hh, mm

	lv_label_set_text_static( mem->lbl, NULL );
	lv_obj_align_to( mem->lbl, mem->btn, LV_ALIGN_OUT_LEFT_MID, -LV_DPI*1/12, 0 );

static void init_status_area(void)
	lv_obj_t * header = sndbx_get_header();
	lv_obj_t * btn  = sndbx_get_settings_btn();

	htd_t *mem = lv_mem_alloc(sizeof(htd_t));

	mem->hdr = header;
	mem->btn = btn;
	mem->lbl = lv_label_create(header);
	lv_obj_set_style_text_font( mem->lbl, SNDBX_FONT_SMALL, 0 );
	mem->buf = lv_mem_alloc(128);
	mem->buf_size = 128;

	mem->buf[0] = '\0';
	lv_label_set_text_static( mem->lbl, mem->buf );
    lv_obj_set_style_text_align( mem->lbl, LV_TEXT_ALIGN_RIGHT, 0 );
	lv_label_set_recolor( mem->lbl, true );

	lv_timer_t * tsk;
	tsk = lv_timer_create(
	header_task( tsk );
	lv_obj_align_to( mem->lbl, mem->btn, LV_ALIGN_OUT_LEFT_MID, -LV_DPI*1/12, 0 );

Take a look at the files in sndbx/src/pages, sndbx_pge_dispatch.c and sndbx_pge_dispatch.h would be good starting points to begin working with.

Hello. thanks for your reply.
After trying to create a large menu using the LV_MENU widget, I get the feeling that your application has more potential for creating a multi-page menu, but there is little information on it and I have to figure out all the subtleties of setting it up and working with it on my own.
I looked at the contents of the files sndbx_pge_dispatch.c/.h, sndbx_pge_lv_demos.c/.h, sndbx_pge_lvgl_apps.c/.h and the like.
Based on them and in their likeness, I created the files sndbx_pge_menu.c/.h in which he described the initial menu of his device.
I figured out how to fill the menu, how to call the functions corresponding to the menu items, how to enable and disable the close button of the active application, how to activate the ‘SETTINGS’ button at the top right.
But I still have questions:

  1. When the application starts, the focus is initially located on the inactive ‘PREV’ button. How can I set the initial focus on another object, for example, on the ‘HOME’ button or on a specific menu item in the button matrix?
  2. In what place should I apply the status area code you provided, tested on version 8.3.4?
  3. Is it possible to demonstrate your code implementing the working menu of this device?

I am sure it is possible, but I have not needed to bother with focus at all. My use cases have all been for embedded system’s with a touch screen and it has never been an issue. I don’t have time to look into changing focus to a different object at the moment. I suggest you ask the question the General discussion topic.

I have updated the zip file to include something a bit more comprehensive than a simple “Hello World” application. It includes the status area I did above as well as usage of the “settings” button.
Simply call sndbx_app_hello_status() from main as you would any other app. (47.8 KB)

I am not sure what you mean by this, but bear in mind the idea and distinction between managed and unmanaged pages.
Unmanaged pages are those that were not specifically written to fit into the sandbox framework, this includes all lvgl example and demo apps (ie all apps that are part of the lvgl repo). Managed apps (and pages) are those that are specifically written with the sandbox framework in mind. sndbx_app_hello_status() and sanbox template page sndbx_pge_templ_dsc are rudimentary examples of a managed app and page.