Index: tools/mkarray.py
===================================================================
--- tools/mkarray.py	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ tools/mkarray.py	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -39,8 +39,8 @@
 def usage(prname):
 	"Print usage syntax"
-	print("%s [--deflate] <DESTINATION> <LABEL> <AS_PROLOG> <SECTION> [SOURCE ...]" % prname)
+	print("%s [--deflate] <DESTINATION> <TYPENAME> <LABEL> <AS_PROLOG> <SECTION> [SOURCE ...]" % prname)
 
 def arg_check():
-	if (len(sys.argv) < 5):
+	if (len(sys.argv) < 6):
 		usage(sys.argv[0])
 		sys.exit()
@@ -66,7 +66,8 @@
 
 	dest = sys.argv[1]
-	label = sys.argv[2]
-	as_prolog = sys.argv[3]
-	section = sys.argv[4]
+	typename = sys.argv[2]
+	label = sys.argv[3]
+	as_prolog = sys.argv[4]
+	section = sys.argv[5]
 
 	timestamp = (1980, 1, 1, 0, 0, 0)
@@ -81,5 +82,5 @@
 	archive = zipfile.ZipFile("%s.zip" % dest, "w", zipfile.ZIP_STORED)
 
-	for src in sys.argv[5:]:
+	for src in sys.argv[6:]:
 		basename = os.path.basename(src)
 		plainname = os.path.splitext(basename)[0]
@@ -147,4 +148,6 @@
 	data += "#include <stdbool.h>\n\n"
 	data += "#define %sS  %u\n\n" % (label.upper(), src_cnt)
+	data += "#ifndef %sS_T_\n" % typename.upper()
+	data += "#define %sS_T_\n\n" % typename.upper()
 	data += "typedef struct {\n"
 	data += "\tconst char *name;\n"
@@ -153,6 +156,7 @@
 	data += "\tsize_t inflated;\n"
 	data += "\tbool compressed;\n"
-	data += "} %s_t;\n\n" % label
-	data += "extern %s_t %ss[];\n\n" % (label, label)
+	data += "} %s_t;\n\n" % typename
+	data += "#endif\n"
+	data += "extern %s_t %ss[];\n\n" % (typename, label)
 	data += "\n".join(header_ctx)
 	data += "\n\n"
@@ -179,5 +183,5 @@
 	data += ' */\n\n'
 	data += "#include \"%s.h\"\n\n" % dest
-	data += "%s_t %ss[] = {\n" % (label, label)
+	data += "%s_t %ss[] = {\n" % (typename, label)
 	data += ",\n".join(desc_ctx)
 	data += "\n"
Index: uspace/app/aboutos/meson.build
===================================================================
--- uspace/app/aboutos/meson.build	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/app/aboutos/meson.build	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -35,5 +35,5 @@
 	input : _images,
 	output : [ 'images.zip' ],
-	command : [ mkarray, '@OUTDIR@', 'images', 'image', uspace_as_prolog, '.data', '@INPUT@' ],
+	command : [ mkarray, '@OUTDIR@', 'images', 'image', 'image', uspace_as_prolog, '.data', '@INPUT@' ],
 )
 _imgs_s = custom_target('aboutos_images.s',
Index: uspace/app/barber/barber.c
===================================================================
--- uspace/app/barber/barber.c	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/app/barber/barber.c	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -50,4 +50,5 @@
 #include <ui/image.h>
 #include "images.h"
+#include "images_tiny.h"
 
 #define NAME  "barber"
@@ -60,7 +61,4 @@
 #define MIN_LOAD  (LOAD_UNIT / 4)
 #define MAX_LOAD  (LOAD_UNIT / 3)
-
-#define FRAME_WIDTH   59
-#define FRAME_HEIGHT  192
 
 #define LED_PERIOD  1000000
@@ -97,4 +95,6 @@
 static unsigned int frame = 0;
 static unsigned int fps = MIN_FPS;
+static gfx_coord_t frame_width;
+static gfx_coord_t frame_height;
 
 static void led_timer_callback(void *);
@@ -119,5 +119,5 @@
 }
 
-static bool decode_frames(gfx_context_t *gc)
+static bool decode_frames(gfx_context_t *gc, image_t *img)
 {
 	gfx_rect_t rect;
@@ -125,5 +125,5 @@
 
 	for (unsigned int i = 0; i < FRAMES; i++) {
-		rc = decode_tga_gz(gc, images[i].addr, images[i].size,
+		rc = decode_tga_gz(gc, img[i].addr, img[i].size,
 		    &frame_bmp[i], &rect);
 		if (rc != EOK) {
@@ -132,5 +132,5 @@
 		}
 
-		(void) rect;
+		(void)rect;
 	}
 
@@ -238,6 +238,6 @@
 	rect.p0.x = 0;
 	rect.p0.y = 0;
-	rect.p1.x = FRAME_WIDTH;
-	rect.p1.y = FRAME_HEIGHT;
+	rect.p1.x = frame_width;
+	rect.p1.y = frame_height;
 
 	ui_image_set_bmp(frame_img, frame_bmp[frame], &rect);
@@ -299,5 +299,5 @@
 int main(int argc, char *argv[])
 {
-	const char *display_spec = UI_DISPLAY_DEFAULT;
+	const char *display_spec = UI_ANY_DEFAULT;
 	barber_t barber;
 	ui_t *ui;
@@ -310,4 +310,5 @@
 	gfx_context_t *gc;
 	gfx_coord2_t off;
+	image_t *img;
 	int i;
 
@@ -355,8 +356,16 @@
 	}
 
+	if (ui_is_textmode(ui)) {
+		frame_width = 10;
+		frame_height = 16;
+	} else {
+		frame_width = 59;
+		frame_height = 192;
+	}
+
 	rect.p0.x = 0;
 	rect.p0.y = 0;
-	rect.p1.x = FRAME_WIDTH;
-	rect.p1.y = FRAME_HEIGHT;
+	rect.p1.x = frame_width;
+	rect.p1.y = frame_height;
 
 	ui_wnd_params_init(&params);
@@ -367,5 +376,5 @@
 	 * to rect
 	 */
-	ui_wdecor_rect_from_app(params.style, &rect, &wrect);
+	ui_wdecor_rect_from_app(ui, params.style, &rect, &wrect);
 	off = wrect.p0;
 	gfx_rect_rtranslate(&off, &wrect, &params.rect);
@@ -384,5 +393,7 @@
 	ui_window_set_cb(window, &window_cb, (void *) &barber);
 
-	if (!decode_frames(gc))
+	img = ui_is_textmode(ui) ? image_tinys : images;
+
+	if (!decode_frames(gc, img))
 		return 1;
 
Index: uspace/app/barber/meson.build
===================================================================
--- uspace/app/barber/meson.build	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/app/barber/meson.build	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -62,4 +62,37 @@
 )
 
+_images_tiny = files(
+	'gfx-tiny/frame01t.tga.gz',
+	'gfx-tiny/frame02t.tga.gz',
+	'gfx-tiny/frame03t.tga.gz',
+	'gfx-tiny/frame04t.tga.gz',
+	'gfx-tiny/frame05t.tga.gz',
+	'gfx-tiny/frame06t.tga.gz',
+	'gfx-tiny/frame07t.tga.gz',
+	'gfx-tiny/frame08t.tga.gz',
+	'gfx-tiny/frame09t.tga.gz',
+	'gfx-tiny/frame10t.tga.gz',
+	'gfx-tiny/frame11t.tga.gz',
+	'gfx-tiny/frame12t.tga.gz',
+	'gfx-tiny/frame13t.tga.gz',
+	'gfx-tiny/frame14t.tga.gz',
+	'gfx-tiny/frame15t.tga.gz',
+	'gfx-tiny/frame16t.tga.gz',
+	'gfx-tiny/frame17t.tga.gz',
+	'gfx-tiny/frame18t.tga.gz',
+	'gfx-tiny/frame19t.tga.gz',
+	'gfx-tiny/frame20t.tga.gz',
+	'gfx-tiny/frame21t.tga.gz',
+	'gfx-tiny/frame22t.tga.gz',
+	'gfx-tiny/frame23t.tga.gz',
+	'gfx-tiny/frame24t.tga.gz',
+	'gfx-tiny/frame25t.tga.gz',
+	'gfx-tiny/frame26t.tga.gz',
+	'gfx-tiny/frame27t.tga.gz',
+	'gfx-tiny/frame28t.tga.gz',
+	'gfx-tiny/frame29t.tga.gz',
+	'gfx-tiny/frame30t.tga.gz',
+)
+
 _tarball = custom_target('barber_images.tar',
 	input: _images,
@@ -70,8 +103,10 @@
 # TODO
 
+# Normal images
+
 _images_zip = custom_target('barber_images.zip',
 	input : _images,
 	output : [ 'images.zip' ],
-	command : [ mkarray, '@OUTDIR@', 'images', 'image', uspace_as_prolog, '.data', '@INPUT@' ],
+	command : [ mkarray, '@OUTDIR@', 'images', 'image', 'image', uspace_as_prolog, '.data', '@INPUT@' ],
 )
 _imgs_s = custom_target('barber_images.s',
@@ -94,3 +129,30 @@
 )
 
-src = [ files('barber.c'), _imgs_s, _imgs_h, _imgs_desc_c ]
+# Tiny images
+
+_images_tiny_zip = custom_target('barber_images_tiny.zip',
+	input : _images_tiny,
+	output : [ 'images_tiny.zip' ],
+	command : [ mkarray, '@OUTDIR@', 'images_tiny', 'image', 'image_tiny', uspace_as_prolog, '.data', '@INPUT@' ],
+)
+_imgs_tiny_s = custom_target('barber_images_tiny.s',
+	input : _images_tiny_zip,
+	output : [ 'images_tiny.s' ],
+	command : [ unzip, '-p', '@INPUT@', 'images_tiny.s' ],
+	capture : true,
+)
+_imgs_tiny_h = custom_target('barber_images_tiny.h',
+	input : _images_tiny_zip,
+	output : [ 'images_tiny.h' ],
+	command : [ unzip, '-p', '@INPUT@', 'images_tiny.h' ],
+	capture : true,
+)
+_imgs_tiny_desc_c = custom_target('barber_images_tiny_desc.c',
+	input : _images_tiny_zip,
+	output : [ 'images_tiny_desc.c' ],
+	command : [ unzip, '-p', '@INPUT@', 'images_tiny_desc.c' ],
+	capture : true,
+)
+
+src = [ files('barber.c'), _imgs_s, _imgs_h, _imgs_desc_c,
+    _imgs_tiny_s, _imgs_tiny_h, _imgs_tiny_desc_c ]
Index: uspace/app/fontedit/fontedit.c
===================================================================
--- uspace/app/fontedit/fontedit.c	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/app/fontedit/fontedit.c	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2022 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * All rights reserved.
  *
@@ -787,5 +787,5 @@
 	 * to rect
 	 */
-	ui_wdecor_rect_from_app(params.style, &rect, &wrect);
+	ui_wdecor_rect_from_app(ui, params.style, &rect, &wrect);
 	off = wrect.p0;
 	gfx_rect_rtranslate(&off, &wrect, &params.rect);
Index: uspace/app/gfxdemo/gfxdemo.c
===================================================================
--- uspace/app/gfxdemo/gfxdemo.c	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/app/gfxdemo/gfxdemo.c	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2023 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * All rights reserved.
  *
@@ -1160,5 +1160,5 @@
 	 * to rect
 	 */
-	ui_wdecor_rect_from_app(params.style, &rect, &wrect);
+	ui_wdecor_rect_from_app(ui, params.style, &rect, &wrect);
 	off = wrect.p0;
 	gfx_rect_rtranslate(&off, &wrect, &params.rect);
Index: uspace/app/terminal/terminal.c
===================================================================
--- uspace/app/terminal/terminal.c	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/app/terminal/terminal.c	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2023 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * Copyright (c) 2012 Petr Koupy
  * All rights reserved.
@@ -974,19 +974,19 @@
 		wparams.placement = ui_wnd_place_top_left;
 
+	rc = ui_create(display_spec, &term->ui);
+	if (rc != EOK) {
+		printf("Error creating UI on %s.\n", display_spec);
+		goto error;
+	}
+
 	/*
 	 * Compute window rectangle such that application area corresponds
 	 * to rect
 	 */
-	ui_wdecor_rect_from_app(wparams.style, &rect, &wrect);
+	ui_wdecor_rect_from_app(term->ui, wparams.style, &rect, &wrect);
 	off = wrect.p0;
 	gfx_rect_rtranslate(&off, &wrect, &wparams.rect);
 
 	term->off = off;
-
-	rc = ui_create(display_spec, &term->ui);
-	if (rc != EOK) {
-		printf("Error creating UI on %s.\n", display_spec);
-		goto error;
-	}
 
 	rc = ui_window_create(term->ui, &wparams, &term->window);
Index: uspace/app/viewer/viewer.c
===================================================================
--- uspace/app/viewer/viewer.c	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/app/viewer/viewer.c	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2020 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * Copyright (c) 2013 Martin Decky
  * All rights reserved.
@@ -314,5 +314,5 @@
 	 * to rect
 	 */
-	ui_wdecor_rect_from_app(params.style, &lrect, &wrect);
+	ui_wdecor_rect_from_app(ui, params.style, &lrect, &wrect);
 	off = wrect.p0;
 	gfx_rect_rtranslate(&off, &wrect, &rect);
Index: uspace/lib/congfx/src/console.c
===================================================================
--- uspace/lib/congfx/src/console.c	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/lib/congfx/src/console.c	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -91,5 +91,5 @@
 	uint8_t attr;
 
-	if ((clr >> 24) == 0) {
+	if ((clr >> 24) == 0xff) {
 		/* RGB (no text) */
 		ch->ch = 0;
Index: uspace/lib/gfx/src/color.c
===================================================================
--- uspace/lib/gfx/src/color.c	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/lib/gfx/src/color.c	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * All rights reserved.
  *
@@ -64,4 +64,5 @@
 	color->g = g;
 	color->b = b;
+	color->attr = 0xff;
 
 	*rcolor = color;
Index: uspace/lib/ui/include/ui/wdecor.h
===================================================================
--- uspace/lib/ui/include/ui/wdecor.h	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/lib/ui/include/ui/wdecor.h	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2023 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * All rights reserved.
  *
@@ -44,4 +44,5 @@
 #include <types/ui/event.h>
 #include <types/ui/resource.h>
+#include <types/ui/ui.h>
 #include <types/ui/wdecor.h>
 
@@ -58,5 +59,5 @@
 extern ui_evclaim_t ui_wdecor_kbd_event(ui_wdecor_t *, kbd_event_t *);
 extern ui_evclaim_t ui_wdecor_pos_event(ui_wdecor_t *, pos_event_t *);
-extern void ui_wdecor_rect_from_app(ui_wdecor_style_t, gfx_rect_t *,
+extern void ui_wdecor_rect_from_app(ui_t *, ui_wdecor_style_t, gfx_rect_t *,
     gfx_rect_t *);
 extern void ui_wdecor_app_from_rect(ui_wdecor_style_t, gfx_rect_t *,
Index: uspace/lib/ui/src/wdecor.c
===================================================================
--- uspace/lib/ui/src/wdecor.c	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/lib/ui/src/wdecor.c	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2023 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * All rights reserved.
  *
@@ -45,4 +45,5 @@
 #include <ui/paint.h>
 #include <ui/pbutton.h>
+#include <ui/ui.h>
 #include <ui/wdecor.h>
 #include "../private/resource.h"
@@ -94,4 +95,8 @@
 	/** Window resizing edge height */
 	wdecor_edge_h = 4,
+	/** Window resizing edge witdth */
+	wdecor_edge_w_text = 1,
+	/** Window resizing edge height */
+	wdecor_edge_h_text = 1,
 	/** Title bar height */
 	wdecor_tbar_h = 22,
@@ -860,22 +865,34 @@
  * and its decoration.
  *
+ * @param ui UI
  * @param style Decoration style
  * @param app Application area rectangle
  * @param rect Place to store (outer) window decoration rectangle
  */
-void ui_wdecor_rect_from_app(ui_wdecor_style_t style, gfx_rect_t *app,
-    gfx_rect_t *rect)
-{
+void ui_wdecor_rect_from_app(ui_t *ui, ui_wdecor_style_t style,
+    gfx_rect_t *app, gfx_rect_t *rect)
+{
+	bool textmode;
+	gfx_coord_t edge_w, edge_h;
 	*rect = *app;
 
+	textmode = ui_is_textmode(ui);
+	if (textmode) {
+		edge_w = wdecor_edge_w_text;
+		edge_h = wdecor_edge_h_text;
+	} else {
+		edge_w = wdecor_edge_w;
+		edge_h = wdecor_edge_h;
+	}
+
 	if ((style & ui_wds_frame) != 0) {
-		rect->p0.x -= wdecor_edge_w;
-		rect->p0.y -= wdecor_edge_h;
-		rect->p1.x += wdecor_edge_w;
-		rect->p1.y += wdecor_edge_h;
-	}
-
-	if ((style & ui_wds_titlebar) != 0)
-		rect->p0.y -= 22;
+		rect->p0.x -= edge_w;
+		rect->p0.y -= edge_h;
+		rect->p1.x += edge_w;
+		rect->p1.y += edge_h;
+	}
+
+	if ((style & ui_wds_titlebar) != 0 && !textmode)
+		rect->p0.y -= wdecor_tbar_h;
 }
 
Index: uspace/lib/ui/test/wdecor.c
===================================================================
--- uspace/lib/ui/test/wdecor.c	(revision cd27cd18681cbc25017b1a9c8213d53faefa675f)
+++ uspace/lib/ui/test/wdecor.c	(revision 211fd689737d35925504cec0c8fb09d1af3bd74d)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2023 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * All rights reserved.
  *
@@ -34,4 +34,5 @@
 #include <ui/pbutton.h>
 #include <ui/resource.h>
+#include <ui/ui.h>
 #include <ui/wdecor.h>
 #include "../private/wdecor.h"
@@ -1322,6 +1323,11 @@
 PCUT_TEST(rect_from_app)
 {
+	errno_t rc;
+	ui_t *ui = NULL;
 	gfx_rect_t arect;
 	gfx_rect_t rect;
+
+	rc = ui_create_disp(NULL, &ui);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
 	arect.p0.x = 14;
@@ -1330,5 +1336,5 @@
 	arect.p1.y = 196;
 
-	ui_wdecor_rect_from_app(ui_wds_none, &arect, &rect);
+	ui_wdecor_rect_from_app(ui, ui_wds_none, &arect, &rect);
 
 	PCUT_ASSERT_INT_EQUALS(14, rect.p0.x);
@@ -1337,5 +1343,5 @@
 	PCUT_ASSERT_INT_EQUALS(196, rect.p1.y);
 
-	ui_wdecor_rect_from_app(ui_wds_frame, &arect, &rect);
+	ui_wdecor_rect_from_app(ui, ui_wds_frame, &arect, &rect);
 
 	PCUT_ASSERT_INT_EQUALS(10, rect.p0.x);
@@ -1344,5 +1350,5 @@
 	PCUT_ASSERT_INT_EQUALS(200, rect.p1.y);
 
-	ui_wdecor_rect_from_app(ui_wds_decorated, &arect, &rect);
+	ui_wdecor_rect_from_app(ui, ui_wds_decorated, &arect, &rect);
 
 	PCUT_ASSERT_INT_EQUALS(10, rect.p0.x);
@@ -1351,4 +1357,5 @@
 	PCUT_ASSERT_INT_EQUALS(200, rect.p1.y);
 
+	ui_destroy(ui);
 }
 
