Index: uspace/app/terminal/main.c
===================================================================
--- uspace/app/terminal/main.c	(revision d284ce9c9580c7380258756c41f4a9b67073797c)
+++ uspace/app/terminal/main.c	(revision f03d1308db413ac682d3d6bf4340b8c21226d67a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2019 Jiri Svoboda
+ * Copyright (c) 2020 Jiri Svoboda
  * All rights reserved.
  *
@@ -33,7 +33,7 @@
  */
 
-#include <display.h>
 #include <stdio.h>
 #include <task.h>
+#include <ui/ui.h>
 #include "terminal.h"
 
@@ -43,11 +43,10 @@
 static void print_syntax(void)
 {
-	printf("Syntax: %s [-d <display>]\n", NAME);
+	printf("Syntax: %s [-d <display-spec>]\n", NAME);
 }
 
 int main(int argc, char *argv[])
 {
-	const char *display_svc = DISPLAY_DEFAULT;
-	display_t *display = NULL;
+	const char *display_spec = UI_DISPLAY_DEFAULT;
 	terminal_t *terminal = NULL;
 	errno_t rc;
@@ -64,5 +63,5 @@
 			}
 
-			display_svc = argv[i++];
+			display_spec = argv[i++];
 		} else {
 			printf("Invalid option '%s'.\n", argv[i]);
@@ -77,15 +76,7 @@
 	}
 
-	rc = display_open(display_svc, &display);
-	if (rc != EOK) {
-		printf("%s: Error opening display.\n", NAME);
+	rc = terminal_create(display_spec, 640, 480, &terminal);
+	if (rc != EOK)
 		return 1;
-	}
-
-	rc = terminal_create(display, 640, 480, &terminal);
-	if (rc != EOK) {
-		display_close(display);
-		return 1;
-	}
 
 	task_retval(0);
Index: uspace/app/terminal/terminal.c
===================================================================
--- uspace/app/terminal/terminal.c	(revision d284ce9c9580c7380258756c41f4a9b67073797c)
+++ uspace/app/terminal/terminal.c	(revision f03d1308db413ac682d3d6bf4340b8c21226d67a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2019 Jiri Svoboda
+ * Copyright (c) 2020 Jiri Svoboda
  * Copyright (c) 2012 Petr Koupy
  * All rights reserved.
@@ -32,5 +32,5 @@
  */
 /**
- * @file Terminal application using display service for output
+ * @file Terminal application
  */
 
@@ -51,5 +51,7 @@
 #include <str.h>
 #include <ui/resource.h>
+#include <ui/ui.h>
 #include <ui/wdecor.h>
+#include <ui/window.h>
 
 #include "terminal.h"
@@ -102,24 +104,16 @@
 };
 
-static void terminal_close_event(void *);
-static void terminal_focus_event(void *);
-static void terminal_kbd_event(void *, kbd_event_t *);
-static void terminal_pos_event(void *, pos_event_t *);
-static void terminal_unfocus_event(void *);
-
-static display_wnd_cb_t terminal_wnd_cb = {
-	.close_event = terminal_close_event,
-	.focus_event = terminal_focus_event,
-	.kbd_event = terminal_kbd_event,
-	.pos_event = terminal_pos_event,
-	.unfocus_event = terminal_unfocus_event
-};
-
-static void terminal_wd_close(ui_wdecor_t *, void *);
-static void terminal_wd_move(ui_wdecor_t *, void *, gfx_coord2_t *);
-
-static ui_wdecor_cb_t wdecor_cb = {
-	.close = terminal_wd_close,
-	.move = terminal_wd_move
+static void terminal_close_event(ui_window_t *, void *);
+static void terminal_focus_event(ui_window_t *, void *);
+static void terminal_kbd_event(ui_window_t *, void *, kbd_event_t *);
+static void terminal_pos_event(ui_window_t *, void *, pos_event_t *);
+static void terminal_unfocus_event(ui_window_t *, void *);
+
+static ui_window_cb_t terminal_window_cb = {
+	.close = terminal_close_event,
+	.focus = terminal_focus_event,
+	.kbd = terminal_kbd_event,
+	.pos = terminal_pos_event,
+	.unfocus = terminal_unfocus_event
 };
 
@@ -677,5 +671,5 @@
 
 /** Handle window close event. */
-static void terminal_close_event(void *arg)
+static void terminal_close_event(ui_window_t *window, void *arg)
 {
 	terminal_t *term = (terminal_t *) arg;
@@ -688,19 +682,15 @@
 
 /** Handle window focus event. */
-static void terminal_focus_event(void *arg)
+static void terminal_focus_event(ui_window_t *window, void *arg)
 {
 	terminal_t *term = (terminal_t *) arg;
 
-	if (term->wdecor != NULL) {
-		ui_wdecor_set_active(term->wdecor, true);
-		ui_wdecor_paint(term->wdecor);
-
-		term->is_focused = true;
-		term_update(term);
-	}
+	term->is_focused = true;
+	term_update(term);
 }
 
 /** Handle window keyboard event */
-static void terminal_kbd_event(void *arg, kbd_event_t *kbd_event)
+static void terminal_kbd_event(ui_window_t *window, void *arg,
+    kbd_event_t *kbd_event)
 {
 	terminal_t *term = (terminal_t *) arg;
@@ -714,14 +704,8 @@
 
 /** Handle window position event */
-static void terminal_pos_event(void *arg, pos_event_t *event)
+static void terminal_pos_event(ui_window_t *window, void *arg, pos_event_t *event)
 {
 	cons_event_t cevent;
 	terminal_t *term = (terminal_t *) arg;
-
-	/* Make sure we don't process events until fully initialized */
-	if (term->wdecor == NULL)
-		return;
-
-	ui_wdecor_pos_event(term->wdecor, event);
 
 	sysarg_t sx = -term->off.x;
@@ -741,44 +725,10 @@
 
 /** Handle window unfocus event. */
-static void terminal_unfocus_event(void *arg)
+static void terminal_unfocus_event(ui_window_t *window, void *arg)
 {
 	terminal_t *term = (terminal_t *) arg;
 
-	if (term->wdecor != NULL) {
-		ui_wdecor_set_active(term->wdecor, false);
-		ui_wdecor_paint(term->wdecor);
-
-		term->is_focused = false;
-		term_update(term);
-	}
-}
-
-/** Window decoration requested window closure.
- *
- * @param wdecor Window decoration
- * @param arg Argument (demo)
- */
-static void terminal_wd_close(ui_wdecor_t *wdecor, void *arg)
-{
-	terminal_t *term = (terminal_t *) arg;
-
-	(void) term;
-
-	// XXX This is not really a clean way of terminating
-	exit(0);
-}
-
-/** Window decoration requested window move.
- *
- * @param wdecor Window decoration
- * @param arg Argument (demo)
- * @param pos Position where the title bar was pressed
- */
-static void terminal_wd_move(ui_wdecor_t *wdecor, void *arg, gfx_coord2_t *pos)
-{
-	terminal_t *term = (terminal_t *) arg;
-
-	if (term->window != NULL)
-		(void) display_window_move_req(term->window, pos);
+	term->is_focused = false;
+	term_update(term);
 }
 
@@ -805,10 +755,10 @@
 }
 
-errno_t terminal_create(display_t *display, sysarg_t width, sysarg_t height,
-    terminal_t **rterm)
+errno_t terminal_create(const char *display_spec, sysarg_t width,
+    sysarg_t height, terminal_t **rterm)
 {
 	terminal_t *term;
 	gfx_bitmap_params_t params;
-	display_wnd_params_t wparams;
+	ui_wnd_params_t wparams;
 	gfx_rect_t rect;
 	gfx_coord2_t off;
@@ -859,5 +809,6 @@
 	rect.p1.y = height;
 
-	display_wnd_params_init(&wparams);
+	ui_wnd_params_init(&wparams);
+	wparams.caption = "Terminal";
 
 	/*
@@ -871,6 +822,11 @@
 	term->off = off;
 
-	rc = display_window_create(display, &wparams, &terminal_wnd_cb,
-	    (void *) term, &term->window);
+	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);
 	if (rc != EOK) {
 		printf("Error creating window.\n");
@@ -878,26 +834,8 @@
 	}
 
-	rc = display_window_get_gc(term->window, &term->gc);
-	if (rc != EOK) {
-		printf("Error getting window GC.\n");
-		goto error;
-	}
-
-	rc = ui_resource_create(term->gc, &term->ui_res);
-	if (rc != EOK) {
-		printf("Error creating UI.\n");
-		goto error;
-	}
-
-	rc = ui_wdecor_create(term->ui_res, "Terminal", &term->wdecor);
-	if (rc != EOK) {
-		printf("Error creating window decoration.\n");
-		goto error;
-	}
-
-	ui_wdecor_set_rect(term->wdecor, &wparams.rect);
-	ui_wdecor_set_cb(term->wdecor, &wdecor_cb, (void *) term);
-
-	(void) ui_wdecor_paint(term->wdecor);
+	term->gc = ui_window_get_gc(term->window);
+	term->ui_res = ui_window_get_res(term->window);
+
+	ui_window_set_cb(term->window, &terminal_window_cb, (void *) term);
 
 	gfx_bitmap_params_init(&params);
@@ -943,4 +881,6 @@
 	getterm(vc, "/app/bdsh");
 
+	term->is_focused = true;
+
 	term->update.p0.x = 0;
 	term->update.p0.y = 0;
@@ -953,12 +893,8 @@
 	return EOK;
 error:
-	if (term->wdecor != NULL)
-		ui_wdecor_destroy(term->wdecor);
-	if (term->ui_res != NULL)
-		ui_resource_destroy(term->ui_res);
-	if (term->gc != NULL)
-		gfx_context_delete(term->gc);
 	if (term->window != NULL)
-		display_window_destroy(term->window);
+		ui_window_destroy(term->window);
+	if (term->ui != NULL)
+		ui_destroy(term->ui);
 	if (term->frontbuf != NULL)
 		chargrid_destroy(term->frontbuf);
Index: uspace/app/terminal/terminal.h
===================================================================
--- uspace/app/terminal/terminal.h	(revision d284ce9c9580c7380258756c41f4a9b67073797c)
+++ uspace/app/terminal/terminal.h	(revision f03d1308db413ac682d3d6bf4340b8c21226d67a)
@@ -38,5 +38,4 @@
 #define TERMINAL_H
 
-#include <display.h>
 #include <errno.h>
 #include <fibril_synch.h>
@@ -50,12 +49,15 @@
 #include <stdatomic.h>
 #include <str.h>
-#include <ui/resource.h>
-#include <ui/wdecor.h>
+#include <ui/ui.h>
+#include <ui/window.h>
 
 #define UTF8_CHAR_BUFFER_SIZE  (STR_BOUNDS(1) + 1)
 
 typedef struct {
-	display_window_t *window;
+	ui_t *ui;
+	ui_window_t *window;
+	ui_resource_t *ui_res;
 	gfx_context_t *gc;
+
 	gfx_bitmap_t *bmp;
 	sysarg_t w;
@@ -64,7 +66,4 @@
 	gfx_coord2_t off;
 	bool is_focused;
-
-	ui_resource_t *ui_res;
-	ui_wdecor_t *wdecor;
 
 	fibril_mutex_t mtx;
@@ -86,5 +85,5 @@
 } terminal_t;
 
-extern errno_t terminal_create(display_t *, sysarg_t, sysarg_t, terminal_t **);
+extern errno_t terminal_create(const char *, sysarg_t, sysarg_t, terminal_t **);
 extern void terminal_destroy(terminal_t *);
 
Index: uspace/lib/ui/include/types/ui/window.h
===================================================================
--- uspace/lib/ui/include/types/ui/window.h	(revision d284ce9c9580c7380258756c41f4a9b67073797c)
+++ uspace/lib/ui/include/types/ui/window.h	(revision f03d1308db413ac682d3d6bf4340b8c21226d67a)
@@ -37,4 +37,5 @@
 #define _UI_TYPES_WINDOW_H
 
+#include <io/kbd_event.h>
 #include <io/pos_event.h>
 
@@ -53,5 +54,8 @@
 typedef struct ui_window_cb {
 	void (*close)(ui_window_t *, void *);
+	void (*focus)(ui_window_t *, void *);
+	void (*kbd)(ui_window_t *, void *, kbd_event_t *);
 	void (*pos)(ui_window_t *, void *, pos_event_t *);
+	void (*unfocus)(ui_window_t *, void *);
 } ui_window_cb_t;
 
Index: uspace/lib/ui/private/window.h
===================================================================
--- uspace/lib/ui/private/window.h	(revision d284ce9c9580c7380258756c41f4a9b67073797c)
+++ uspace/lib/ui/private/window.h	(revision f03d1308db413ac682d3d6bf4340b8c21226d67a)
@@ -40,4 +40,5 @@
 #include <display.h>
 #include <gfx/context.h>
+#include <io/kbd_event.h>
 #include <io/pos_event.h>
 
@@ -64,5 +65,8 @@
 
 extern void ui_window_close(ui_window_t *);
+extern void ui_window_focus(ui_window_t *);
+extern void ui_window_kbd(ui_window_t *, kbd_event_t *);
 extern void ui_window_pos(ui_window_t *, pos_event_t *);
+extern void ui_window_unfocus(ui_window_t *);
 
 #endif
Index: uspace/lib/ui/src/window.c
===================================================================
--- uspace/lib/ui/src/window.c	(revision d284ce9c9580c7380258756c41f4a9b67073797c)
+++ uspace/lib/ui/src/window.c	(revision f03d1308db413ac682d3d6bf4340b8c21226d67a)
@@ -37,4 +37,5 @@
 #include <errno.h>
 #include <gfx/context.h>
+#include <io/kbd_event.h>
 #include <io/pos_event.h>
 #include <mem.h>
@@ -221,4 +222,6 @@
 		ui_wdecor_paint(window->wdecor);
 	}
+
+	ui_window_focus(window);
 }
 
@@ -229,5 +232,5 @@
 
 	(void) window;
-	(void) kbd_event;
+	ui_window_kbd(window, kbd_event);
 }
 
@@ -254,4 +257,6 @@
 		ui_wdecor_paint(window->wdecor);
 	}
+
+	ui_window_unfocus(window);
 }
 
@@ -291,4 +296,24 @@
 }
 
+/** Send window focus event.
+ *
+ * @param window Window
+ */
+void ui_window_focus(ui_window_t *window)
+{
+	if (window->cb != NULL && window->cb->focus != NULL)
+		window->cb->focus(window, window->arg);
+}
+
+/** Send window keyboard event.
+ *
+ * @param window Window
+ */
+void ui_window_kbd(ui_window_t *window, kbd_event_t *kbd)
+{
+	if (window->cb != NULL && window->cb->kbd != NULL)
+		window->cb->kbd(window, window->arg, kbd);
+}
+
 /** Send window position event.
  *
@@ -301,4 +326,14 @@
 }
 
+/** Send window unfocus event.
+ *
+ * @param window Window
+ */
+void ui_window_unfocus(ui_window_t *window)
+{
+	if (window->cb != NULL && window->cb->unfocus != NULL)
+		window->cb->unfocus(window, window->arg);
+}
+
 /** @}
  */
Index: uspace/lib/ui/test/window.c
===================================================================
--- uspace/lib/ui/test/window.c	(revision d284ce9c9580c7380258756c41f4a9b67073797c)
+++ uspace/lib/ui/test/window.c	(revision f03d1308db413ac682d3d6bf4340b8c21226d67a)
@@ -29,4 +29,5 @@
 #include <gfx/context.h>
 #include <gfx/coord.h>
+#include <io/kbd_event.h>
 #include <io/pos_event.h>
 #include <mem.h>
@@ -43,9 +44,15 @@
 
 static void test_window_close(ui_window_t *, void *);
+static void test_window_focus(ui_window_t *, void *);
+static void test_window_kbd(ui_window_t *, void *, kbd_event_t *);
 static void test_window_pos(ui_window_t *, void *, pos_event_t *);
+static void test_window_unfocus(ui_window_t *, void *);
 
 static ui_window_cb_t test_window_cb = {
 	.close = test_window_close,
-	.pos = test_window_pos
+	.focus = test_window_focus,
+	.kbd = test_window_kbd,
+	.pos = test_window_pos,
+	.unfocus = test_window_unfocus
 };
 
@@ -55,6 +62,10 @@
 typedef struct {
 	bool close;
+	bool focus;
+	bool kbd;
+	kbd_event_t kbd_event;
 	bool pos;
 	pos_event_t pos_event;
+	bool unfocus;
 } test_cb_resp_t;
 
@@ -151,4 +162,86 @@
 	ui_window_close(window);
 	PCUT_ASSERT_TRUE(resp.close);
+
+	ui_window_destroy(window);
+	ui_destroy(ui);
+}
+
+/** ui_window_focus() calls focus callback set via ui_window_set_cb() */
+PCUT_TEST(focus)
+{
+	errno_t rc;
+	ui_t *ui = NULL;
+	ui_wnd_params_t params;
+	ui_window_t *window = NULL;
+	test_cb_resp_t resp;
+
+	rc = ui_create_disp(NULL, &ui);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	ui_wnd_params_init(&params);
+	params.caption = "Hello";
+
+	rc = ui_window_create(ui, &params, &window);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(window);
+
+	/* Focus callback with no callbacks set */
+	ui_window_focus(window);
+
+	/* Focus callback with focus callback not implemented */
+	ui_window_set_cb(window, &dummy_window_cb, NULL);
+	ui_window_focus(window);
+
+	/* Focus callback with real callback set */
+	resp.close = false;
+	ui_window_set_cb(window, &test_window_cb, &resp);
+	ui_window_focus(window);
+	PCUT_ASSERT_TRUE(resp.focus);
+
+	ui_window_destroy(window);
+	ui_destroy(ui);
+}
+
+/** ui_window_kbd() calls kbd callback set via ui_window_set_cb() */
+PCUT_TEST(kbd)
+{
+	errno_t rc;
+	ui_t *ui = NULL;
+	ui_wnd_params_t params;
+	ui_window_t *window = NULL;
+	kbd_event_t kbd_event;
+	test_cb_resp_t resp;
+
+	rc = ui_create_disp(NULL, &ui);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	ui_wnd_params_init(&params);
+	params.caption = "Hello";
+
+	rc = ui_window_create(ui, &params, &window);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(window);
+
+	kbd_event.type = POS_PRESS;
+	kbd_event.key = KC_X;
+	kbd_event.mods = 0;
+	kbd_event.c = 'x';
+
+	/* Kbd callback with no callbacks set */
+	ui_window_kbd(window, &kbd_event);
+
+	/* Kbd callback with kbd callback not implemented */
+	ui_window_set_cb(window, &dummy_window_cb, NULL);
+	ui_window_kbd(window, &kbd_event);
+
+	/* Kbd callback with real callback set */
+	resp.kbd = false;
+	ui_window_set_cb(window, &test_window_cb, &resp);
+	ui_window_kbd(window, &kbd_event);
+	PCUT_ASSERT_TRUE(resp.kbd);
+	PCUT_ASSERT_EQUALS(kbd_event.type, resp.kbd_event.type);
+	PCUT_ASSERT_INT_EQUALS(kbd_event.key, resp.kbd_event.key);
+	PCUT_ASSERT_INT_EQUALS(kbd_event.mods, resp.kbd_event.mods);
+	PCUT_ASSERT_INT_EQUALS(kbd_event.c, resp.kbd_event.c);
 
 	ui_window_destroy(window);
@@ -204,4 +297,40 @@
 }
 
+/** ui_window_unfocus() calls unfocus callback set via ui_window_set_cb() */
+PCUT_TEST(unfocus)
+{
+	errno_t rc;
+	ui_t *ui = NULL;
+	ui_wnd_params_t params;
+	ui_window_t *window = NULL;
+	test_cb_resp_t resp;
+
+	rc = ui_create_disp(NULL, &ui);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	ui_wnd_params_init(&params);
+	params.caption = "Hello";
+
+	rc = ui_window_create(ui, &params, &window);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(window);
+
+	/* Unfocus callback with no callbacks set */
+	ui_window_unfocus(window);
+
+	/* Unfocus callback with unfocus callback not implemented */
+	ui_window_set_cb(window, &dummy_window_cb, NULL);
+	ui_window_unfocus(window);
+
+	/* Unfocus callback with real callback set */
+	resp.close = false;
+	ui_window_set_cb(window, &test_window_cb, &resp);
+	ui_window_unfocus(window);
+	PCUT_ASSERT_TRUE(resp.unfocus);
+
+	ui_window_destroy(window);
+	ui_destroy(ui);
+}
+
 static void test_window_close(ui_window_t *window, void *arg)
 {
@@ -209,4 +338,20 @@
 
 	resp->close = true;
+}
+
+static void test_window_focus(ui_window_t *window, void *arg)
+{
+	test_cb_resp_t *resp = (test_cb_resp_t *) arg;
+
+	resp->focus = true;
+}
+
+static void test_window_kbd(ui_window_t *window, void *arg,
+    kbd_event_t *event)
+{
+	test_cb_resp_t *resp = (test_cb_resp_t *) arg;
+
+	resp->kbd = true;
+	resp->kbd_event = *event;
 }
 
@@ -220,3 +365,10 @@
 }
 
+static void test_window_unfocus(ui_window_t *window, void *arg)
+{
+	test_cb_resp_t *resp = (test_cb_resp_t *) arg;
+
+	resp->unfocus = true;
+}
+
 PCUT_EXPORT(window);
