Index: uspace/lib/ui/test/wdecor.c
===================================================================
--- uspace/lib/ui/test/wdecor.c	(revision 46bd63c90e62ae2887633555d123a6aa959d3b05)
+++ uspace/lib/ui/test/wdecor.c	(revision 6a0b2cc0082e02f5fddd7bb03523eba5cfce193c)
@@ -62,4 +62,5 @@
 };
 
+static void test_wdecor_sysmenu(ui_wdecor_t *, void *, sysarg_t);
 static void test_wdecor_minimize(ui_wdecor_t *, void *);
 static void test_wdecor_maximize(ui_wdecor_t *, void *);
@@ -72,4 +73,5 @@
 
 static ui_wdecor_cb_t test_wdecor_cb = {
+	.sysmenu = test_wdecor_sysmenu,
 	.minimize = test_wdecor_minimize,
 	.maximize = test_wdecor_maximize,
@@ -102,4 +104,5 @@
 
 typedef struct {
+	bool sysmenu;
 	bool minimize;
 	bool maximize;
@@ -109,4 +112,5 @@
 	gfx_coord2_t pos;
 	sysarg_t pos_id;
+	sysarg_t idev_id;
 	bool resize;
 	ui_wdecor_rsztype_t rsztype;
@@ -241,4 +245,32 @@
 	rc = gfx_context_delete(gc);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+}
+
+/** Test ui_wdecor_sysmenu() */
+PCUT_TEST(sysmenu)
+{
+	errno_t rc;
+	ui_wdecor_t *wdecor;
+	test_cb_resp_t resp;
+
+	rc = ui_wdecor_create(NULL, "Hello", ui_wds_none, &wdecor);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Sysmenu callback with no callbacks set */
+	ui_wdecor_sysmenu(wdecor, 42);
+
+	/* Sysmenu callback with sysmenu callback not implemented */
+	ui_wdecor_set_cb(wdecor, &dummy_wdecor_cb, NULL);
+	ui_wdecor_sysmenu(wdecor, 42);
+
+	/* Sysmenu callback with real callback set */
+	resp.sysmenu = false;
+	resp.idev_id = 0;
+	ui_wdecor_set_cb(wdecor, &test_wdecor_cb, &resp);
+	ui_wdecor_sysmenu(wdecor, 42);
+	PCUT_ASSERT_TRUE(resp.sysmenu);
+	PCUT_ASSERT_INT_EQUALS(42, resp.idev_id);
+
+	ui_wdecor_destroy(wdecor);
 }
 
@@ -544,4 +576,56 @@
 	PCUT_ASSERT_INT_EQUALS(event.hpos, resp.pos.x);
 	PCUT_ASSERT_INT_EQUALS(event.vpos, resp.pos.y);
+
+	ui_wdecor_destroy(wdecor);
+	ui_resource_destroy(resource);
+
+	rc = gfx_context_delete(gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+}
+
+/** Pressing F9 generates sysmenu event */
+PCUT_TEST(kbd_f9_sysmenu)
+{
+	errno_t rc;
+	gfx_rect_t rect;
+	kbd_event_t event;
+	gfx_context_t *gc = NULL;
+	test_gc_t tgc;
+	test_cb_resp_t resp;
+	ui_resource_t *resource = NULL;
+	ui_wdecor_t *wdecor;
+
+	memset(&tgc, 0, sizeof(tgc));
+	rc = gfx_context_new(&ops, &tgc, &gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ui_resource_create(gc, false, &resource);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(resource);
+
+	rc = ui_wdecor_create(resource, "Hello", ui_wds_decorated, &wdecor);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rect.p0.x = 10;
+	rect.p0.y = 20;
+	rect.p1.x = 100;
+	rect.p1.y = 200;
+
+	ui_wdecor_set_rect(wdecor, &rect);
+
+	ui_wdecor_set_cb(wdecor, &test_wdecor_cb, (void *) &resp);
+
+	resp.move = false;
+	resp.pos.x = 0;
+	resp.pos.y = 0;
+
+	event.type = KEY_PRESS;
+	event.mods = 0;
+	event.key = KC_F9;
+	event.kbd_id = 42;
+	ui_wdecor_kbd_event(wdecor, &event);
+
+	PCUT_ASSERT_TRUE(resp.sysmenu);
+	PCUT_ASSERT_INT_EQUALS(event.kbd_id, resp.idev_id);
 
 	ui_wdecor_destroy(wdecor);
@@ -1111,4 +1195,13 @@
 }
 
+static void test_wdecor_sysmenu(ui_wdecor_t *wdecor, void *arg,
+    sysarg_t idev_id)
+{
+	test_cb_resp_t *resp = (test_cb_resp_t *) arg;
+
+	resp->sysmenu = true;
+	resp->idev_id = idev_id;
+}
+
 static void test_wdecor_minimize(ui_wdecor_t *wdecor, void *arg)
 {
Index: uspace/lib/ui/test/window.c
===================================================================
--- uspace/lib/ui/test/window.c	(revision 46bd63c90e62ae2887633555d123a6aa959d3b05)
+++ uspace/lib/ui/test/window.c	(revision 6a0b2cc0082e02f5fddd7bb03523eba5cfce193c)
@@ -45,4 +45,5 @@
 PCUT_TEST_SUITE(window);
 
+static void test_window_sysmenu(ui_window_t *, void *, sysarg_t);
 static void test_window_minimize(ui_window_t *, void *);
 static void test_window_maximize(ui_window_t *, void *);
@@ -56,4 +57,5 @@
 
 static ui_window_cb_t test_window_cb = {
+	.sysmenu = test_window_sysmenu,
 	.minimize = test_window_minimize,
 	.maximize = test_window_maximize,
@@ -82,4 +84,6 @@
 typedef struct {
 	errno_t rc;
+	bool sysmenu;
+	sysarg_t sysmenu_idev_id;
 	bool minimize;
 	bool maximize;
@@ -544,4 +548,42 @@
 }
 
+/** ui_window_send_sysmenu() calls sysmenu callback set via ui_window_set_cb() */
+PCUT_TEST(send_sysmenu)
+{
+	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);
+
+	/* Sysmenu callback with no callbacks set */
+	ui_window_send_sysmenu(window, 42);
+
+	/* Sysmenu callback with sysmenu callback not implemented */
+	ui_window_set_cb(window, &dummy_window_cb, NULL);
+	ui_window_send_sysmenu(window, 42);
+
+	/* Sysmenu callback with real callback set */
+	resp.sysmenu = false;
+	resp.sysmenu_idev_id = 0;
+	ui_window_set_cb(window, &test_window_cb, &resp);
+	ui_window_send_sysmenu(window, 42);
+	PCUT_ASSERT_TRUE(resp.sysmenu);
+	PCUT_ASSERT_INT_EQUALS(42, resp.sysmenu_idev_id);
+
+	ui_window_destroy(window);
+	ui_destroy(ui);
+}
+
 /** ui_window_send_minimize() calls minimize callback set via ui_window_set_cb() */
 PCUT_TEST(send_minimize)
@@ -894,4 +936,12 @@
 }
 
+static void test_window_sysmenu(ui_window_t *window, void *arg, sysarg_t idev_id)
+{
+	test_cb_resp_t *resp = (test_cb_resp_t *) arg;
+
+	resp->sysmenu = true;
+	resp->sysmenu_idev_id = idev_id;
+}
+
 static void test_window_minimize(ui_window_t *window, void *arg)
 {
