Index: uspace/lib/display/include/types/display/wndparams.h
===================================================================
--- uspace/lib/display/include/types/display/wndparams.h	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/lib/display/include/types/display/wndparams.h	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2019 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -38,4 +38,10 @@
 #include <gfx/coord.h>
 
+/** Window flags */
+typedef enum {
+	/** Popup window (capture events, no focus) */
+	wndf_popup = 0x1
+} display_wnd_flags_t;
+
 /** Parameters for a new window.
  *
@@ -50,4 +56,6 @@
 	/** Minimum size (when being resized) */
 	gfx_coord2_t min_size;
+	/** Flags */
+	display_wnd_flags_t flags;
 } display_wnd_params_t;
 
Index: uspace/lib/ui/include/types/ui/window.h
===================================================================
--- uspace/lib/ui/include/types/ui/window.h	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/lib/ui/include/types/ui/window.h	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -63,4 +63,10 @@
 } ui_wnd_placement_t;
 
+/** Window flags */
+typedef enum {
+	/** Popup window */
+	ui_wndf_popup = 0x1
+} ui_wnd_flags_t;
+
 /** Window parameters */
 typedef struct {
@@ -73,4 +79,6 @@
 	/** Window placement */
 	ui_wnd_placement_t placement;
+	/** Window flags */
+	ui_wnd_flags_t flags;
 	/** Parent rectangle for popup windows */
 	gfx_rect_t prect;
Index: uspace/lib/ui/include/ui/window.h
===================================================================
--- uspace/lib/ui/include/ui/window.h	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/lib/ui/include/ui/window.h	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2020 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
Index: uspace/lib/ui/src/popup.c
===================================================================
--- uspace/lib/ui/src/popup.c	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/lib/ui/src/popup.c	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -94,4 +94,5 @@
 	wparams.style &= ~ui_wds_decorated;
 	wparams.placement = ui_wnd_place_popup;
+	wparams.flags |= ui_wndf_popup;
 
 	/* Compute position of parent rectangle relative to the screen */
Index: uspace/lib/ui/src/window.c
===================================================================
--- uspace/lib/ui/src/window.c	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/lib/ui/src/window.c	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -188,4 +188,7 @@
 	gfx_rect_dims(&params->rect, &dparams.min_size);
 
+	if ((params->flags & ui_wndf_popup) != 0)
+		dparams.flags |= wndf_popup;
+
 	if (ui->display != NULL) {
 		if (params->placement != ui_wnd_place_default) {
Index: uspace/srv/hid/display/client.c
===================================================================
--- uspace/srv/hid/display/client.c	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/srv/hid/display/client.c	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2019 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -115,5 +115,5 @@
 	seat = ds_display_first_seat(wnd->display);
 	while (seat != NULL) {
-		ds_seat_evac_focus(seat, wnd);
+		ds_seat_evac_wnd_refs(seat, wnd);
 		seat = ds_display_next_seat(seat);
 	}
Index: uspace/srv/hid/display/dsops.c
===================================================================
--- uspace/srv/hid/display/dsops.c	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/srv/hid/display/dsops.c	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2019 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -75,5 +75,4 @@
 	errno_t rc;
 	ds_client_t *client = (ds_client_t *) arg;
-	ds_seat_t *seat;
 	ds_window_t *wnd;
 
@@ -92,12 +91,4 @@
 	    wnd->id);
 
-	/* XXX All the below should probably be part of ds_window_create() */
-	wnd->dpos.x = ((wnd->id - 1) & 1) * 400;
-	wnd->dpos.y = ((wnd->id - 1) & 2) / 2 * 300;
-
-	seat = ds_display_first_seat(client->display);
-	ds_seat_set_focus(seat, wnd);
-	(void) ds_display_paint(wnd->display, NULL);
-
 	ds_display_unlock(client->display);
 
Index: uspace/srv/hid/display/seat.c
===================================================================
--- uspace/srv/hid/display/seat.c	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/srv/hid/display/seat.c	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2019 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -106,12 +106,23 @@
 }
 
-/** Evacuate focus from window.
+/** Set seat popup window.
+ *
+ * @param seat Seat
+ * @param wnd Popup window
+ */
+void ds_seat_set_popup(ds_seat_t *seat, ds_window_t *wnd)
+{
+	seat->popup = wnd;
+}
+
+/** Evacuate seat references to window.
  *
  * If seat's focus is @a wnd, it will be set to a different window.
+ * If seat's popup window is @a wnd, it will be set to NULL.
  *
  * @param seat Seat
  * @param wnd Window to evacuate focus from
  */
-void ds_seat_evac_focus(ds_seat_t *seat, ds_window_t *wnd)
+void ds_seat_evac_wnd_refs(ds_seat_t *seat, ds_window_t *wnd)
 {
 	ds_window_t *nwnd;
@@ -126,4 +137,7 @@
 		ds_seat_set_focus(seat, nwnd);
 	}
+
+	if (seat->popup == wnd)
+		seat->popup = NULL;
 }
 
@@ -168,5 +182,8 @@
 	}
 
-	dwindow = seat->focus;
+	dwindow = seat->popup;
+	if (dwindow == NULL)
+		dwindow = seat->focus;
+
 	if (dwindow == NULL)
 		return EOK;
@@ -328,5 +345,5 @@
 	/* Focus window on button press */
 	if (event->type == PTD_PRESS && event->btn_num == 1) {
-		if (wnd != NULL) {
+		if (wnd != NULL && (wnd->flags & wndf_popup) == 0) {
 			ds_seat_set_focus(seat, wnd);
 		}
@@ -410,4 +427,15 @@
 
 	wnd = ds_display_window_by_pos(seat->display, &seat->pntpos);
+	/*
+	 * Deliver event to popup window, unless the pointer is over
+	 * it (in which case it will be delivered to that window
+	 * below, anyway.
+	 */
+	if (seat->popup != wnd && seat->popup != NULL) {
+		rc = ds_window_post_pos_event(seat->popup, event);
+		if (rc != EOK)
+			return rc;
+	}
+
 	if (seat->focus != wnd && seat->focus != NULL) {
 		rc = ds_window_post_pos_event(seat->focus, event);
Index: uspace/srv/hid/display/seat.h
===================================================================
--- uspace/srv/hid/display/seat.h	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/srv/hid/display/seat.h	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2019 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -49,5 +49,6 @@
 extern void ds_seat_destroy(ds_seat_t *);
 extern void ds_seat_set_focus(ds_seat_t *, ds_window_t *);
-extern void ds_seat_evac_focus(ds_seat_t *, ds_window_t *);
+extern void ds_seat_set_popup(ds_seat_t *, ds_window_t *);
+extern void ds_seat_evac_wnd_refs(ds_seat_t *, ds_window_t *);
 extern void ds_seat_switch_focus(ds_seat_t *);
 extern errno_t ds_seat_post_kbd_event(ds_seat_t *, kbd_event_t *);
Index: uspace/srv/hid/display/test/client.c
===================================================================
--- uspace/srv/hid/display/test/client.c	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/srv/hid/display/test/client.c	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2019 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -34,4 +34,5 @@
 #include "../client.h"
 #include "../display.h"
+#include "../seat.h"
 #include "../window.h"
 
@@ -78,14 +79,19 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *w0;
 	ds_window_t *w1;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
-	errno_t rc;
-
-	rc = ds_display_create(NULL, df_none, &disp);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	rc = ds_client_create(disp, &test_ds_client_cb, NULL, &client);
+	bool called_cb = NULL;
+	errno_t rc;
+
+	rc = ds_display_create(NULL, df_none, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, &seat);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -114,4 +120,5 @@
 	ds_window_destroy(w0);
 	ds_window_destroy(w1);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -123,14 +130,19 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *w0;
 	ds_window_t *w1;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
-	errno_t rc;
-
-	rc = ds_display_create(NULL, df_none, &disp);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	rc = ds_client_create(disp, &test_ds_client_cb, NULL, &client);
+	bool called_cb = NULL;
+	errno_t rc;
+
+	rc = ds_display_create(NULL, df_none, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, &seat);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -156,4 +168,5 @@
 	ds_window_destroy(w0);
 	ds_window_destroy(w1);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -165,4 +178,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -178,12 +192,21 @@
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
-	display_wnd_params_init(&params);
-	params.rect.p0.x = params.rect.p0.y = 0;
-	params.rect.p1.x = params.rect.p1.y = 1;
-
-	rc = ds_window_create(client, &params, &wnd);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	PCUT_ASSERT_FALSE(called_cb);
+	rc = ds_seat_create(disp, &seat);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	display_wnd_params_init(&params);
+	params.rect.p0.x = params.rect.p0.y = 0;
+	params.rect.p1.x = params.rect.p1.y = 1;
+
+	rc = ds_window_create(client, &params, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* New window gets focused event */
+	PCUT_ASSERT_TRUE(called_cb);
+
+	rc = ds_client_get_event(client, &rwindow, &revent);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	called_cb = false;
 
 	rc = ds_client_get_event(client, &rwindow, &revent);
@@ -203,4 +226,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -212,4 +236,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -225,12 +250,21 @@
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
-	display_wnd_params_init(&params);
-	params.rect.p0.x = params.rect.p0.y = 0;
-	params.rect.p1.x = params.rect.p1.y = 1;
-
-	rc = ds_window_create(client, &params, &wnd);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	PCUT_ASSERT_FALSE(called_cb);
+	rc = ds_seat_create(disp, &seat);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	display_wnd_params_init(&params);
+	params.rect.p0.x = params.rect.p0.y = 0;
+	params.rect.p1.x = params.rect.p1.y = 1;
+
+	rc = ds_window_create(client, &params, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* New window gets focused event */
+	PCUT_ASSERT_TRUE(called_cb);
+
+	rc = ds_client_get_event(client, &rwindow, &revent);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	called_cb = false;
 
 	rc = ds_client_get_event(client, &rwindow, &revent);
@@ -250,4 +284,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -259,4 +294,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -273,10 +309,24 @@
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
-	display_wnd_params_init(&params);
-	params.rect.p0.x = params.rect.p0.y = 0;
-	params.rect.p1.x = params.rect.p1.y = 1;
-
-	rc = ds_window_create(client, &params, &wnd);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	rc = ds_seat_create(disp, &seat);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	display_wnd_params_init(&params);
+	params.rect.p0.x = params.rect.p0.y = 0;
+	params.rect.p1.x = params.rect.p1.y = 1;
+
+	rc = ds_window_create(client, &params, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* New window gets focused event */
+	PCUT_ASSERT_TRUE(called_cb);
+
+	rc = ds_client_get_event(client, &rwindow, &revent);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	called_cb = false;
+
+	rc = ds_client_get_event(client, &rwindow, &revent);
+	PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
 
 	event.type = KEY_PRESS;
@@ -284,9 +334,4 @@
 	event.mods = 0;
 	event.c = L'\0';
-
-	PCUT_ASSERT_FALSE(called_cb);
-
-	rc = ds_client_get_event(client, &rwindow, &revent);
-	PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
 
 	rc = ds_client_post_kbd_event(client, wnd, &event);
@@ -307,4 +352,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -316,4 +362,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -330,19 +377,30 @@
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
-	display_wnd_params_init(&params);
-	params.rect.p0.x = params.rect.p0.y = 0;
-	params.rect.p1.x = params.rect.p1.y = 1;
-
-	rc = ds_window_create(client, &params, &wnd);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	rc = ds_seat_create(disp, &seat);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	display_wnd_params_init(&params);
+	params.rect.p0.x = params.rect.p0.y = 0;
+	params.rect.p1.x = params.rect.p1.y = 1;
+
+	rc = ds_window_create(client, &params, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* New window gets focused event */
+	PCUT_ASSERT_TRUE(called_cb);
+
+	rc = ds_client_get_event(client, &rwindow, &revent);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	called_cb = false;
+
+	PCUT_ASSERT_FALSE(called_cb);
+
+	rc = ds_client_get_event(client, &rwindow, &revent);
+	PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
 
 	event.type = POS_PRESS;
 	event.hpos = 1;
 	event.vpos = 2;
-
-	PCUT_ASSERT_FALSE(called_cb);
-
-	rc = ds_client_get_event(client, &rwindow, &revent);
-	PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
 
 	rc = ds_client_post_pos_event(client, wnd, &event);
@@ -362,4 +420,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -371,4 +430,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -385,10 +445,26 @@
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
-	display_wnd_params_init(&params);
-	params.rect.p0.x = params.rect.p0.y = 0;
-	params.rect.p1.x = params.rect.p1.y = 1;
-
-	rc = ds_window_create(client, &params, &wnd);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	rc = ds_seat_create(disp, &seat);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	display_wnd_params_init(&params);
+	params.rect.p0.x = params.rect.p0.y = 0;
+	params.rect.p1.x = params.rect.p1.y = 1;
+
+	rc = ds_window_create(client, &params, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* New window gets focused event */
+	PCUT_ASSERT_TRUE(called_cb);
+
+	rc = ds_client_get_event(client, &rwindow, &revent);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	called_cb = false;
+
+	PCUT_ASSERT_FALSE(called_cb);
+
+	rc = ds_client_get_event(client, &rwindow, &revent);
+	PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
 
 	rect.p0.x = 1;
@@ -396,9 +472,4 @@
 	rect.p1.x = 3;
 	rect.p1.y = 4;
-
-	PCUT_ASSERT_FALSE(called_cb);
-
-	rc = ds_client_get_event(client, &rwindow, &revent);
-	PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
 
 	rc = ds_client_post_resize_event(client, wnd, &rect);
@@ -419,4 +490,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -428,4 +500,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -441,12 +514,21 @@
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
-	display_wnd_params_init(&params);
-	params.rect.p0.x = params.rect.p0.y = 0;
-	params.rect.p1.x = params.rect.p1.y = 1;
-
-	rc = ds_window_create(client, &params, &wnd);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	PCUT_ASSERT_FALSE(called_cb);
+	rc = ds_seat_create(disp, &seat);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	display_wnd_params_init(&params);
+	params.rect.p0.x = params.rect.p0.y = 0;
+	params.rect.p1.x = params.rect.p1.y = 1;
+
+	rc = ds_window_create(client, &params, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* New window gets focused event */
+	PCUT_ASSERT_TRUE(called_cb);
+
+	rc = ds_client_get_event(client, &rwindow, &revent);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	called_cb = false;
 
 	rc = ds_client_get_event(client, &rwindow, &revent);
@@ -466,4 +548,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -479,4 +562,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -489,11 +573,15 @@
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
-	display_wnd_params_init(&params);
-	params.rect.p0.x = params.rect.p0.y = 0;
-	params.rect.p1.x = params.rect.p1.y = 1;
-
-	rc = ds_window_create(client, &params, &wnd);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
+	rc = ds_seat_create(disp, &seat);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	display_wnd_params_init(&params);
+	params.rect.p0.x = params.rect.p0.y = 0;
+	params.rect.p1.x = params.rect.p1.y = 1;
+
+	rc = ds_window_create(client, &params, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
Index: uspace/srv/hid/display/test/display.c
===================================================================
--- uspace/srv/hid/display/test/display.c	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/srv/hid/display/test/display.c	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -94,14 +94,19 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *w0;
 	ds_window_t *w1;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
-	errno_t rc;
-
-	rc = ds_display_create(NULL, df_none, &disp);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	rc = ds_client_create(disp, &test_ds_client_cb, NULL, &client);
+	bool called_cb = false;
+	errno_t rc;
+
+	rc = ds_display_create(NULL, df_none, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, &seat);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -148,4 +153,5 @@
 	ds_window_destroy(w0);
 	ds_window_destroy(w1);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -157,4 +163,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *w0;
 	ds_window_t *w1;
@@ -162,10 +169,14 @@
 	display_wnd_params_t params;
 	gfx_coord2_t pos;
-	errno_t rc;
-
-	rc = ds_display_create(NULL, df_none, &disp);
-	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
-
-	rc = ds_client_create(disp, &test_ds_client_cb, NULL, &client);
+	bool called_cb = false;
+	errno_t rc;
+
+	rc = ds_display_create(NULL, df_none, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, &seat);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -198,4 +209,5 @@
 	ds_window_destroy(w0);
 	ds_window_destroy(w1);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
Index: uspace/srv/hid/display/test/seat.c
===================================================================
--- uspace/srv/hid/display/test/seat.c	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/srv/hid/display/test/seat.c	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2019 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -126,5 +126,5 @@
 	called_cb = false;
 
-	ds_seat_evac_focus(seat, w1);
+	ds_seat_evac_wnd_refs(seat, w1);
 	PCUT_ASSERT_EQUALS(w0, seat->focus);
 	PCUT_ASSERT_TRUE(called_cb);
@@ -172,7 +172,49 @@
 	called_cb = false;
 
-	ds_seat_evac_focus(seat, wnd);
+	ds_seat_evac_wnd_refs(seat, wnd);
 	PCUT_ASSERT_NULL(seat->focus);
 	PCUT_ASSERT_TRUE(called_cb);
+
+	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
+	ds_client_destroy(client);
+	ds_display_destroy(disp);
+}
+
+/** Evacuate popup reference from window.
+ *
+ * After evacuating no window should be set as the popup
+ */
+PCUT_TEST(evac_popup)
+{
+	ds_display_t *disp;
+	ds_client_t *client;
+	ds_seat_t *seat;
+	ds_window_t *wnd;
+	display_wnd_params_t params;
+	bool called_cb = false;
+	errno_t rc;
+
+	rc = ds_display_create(NULL, df_none, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, &seat);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	display_wnd_params_init(&params);
+	params.rect.p0.x = params.rect.p0.y = 0;
+	params.rect.p1.x = params.rect.p1.y = 1;
+	params.flags |= wndf_popup;
+
+	rc = ds_window_create(client, &params, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	PCUT_ASSERT_EQUALS(wnd, seat->popup);
+
+	ds_seat_evac_wnd_refs(seat, wnd);
+	PCUT_ASSERT_NULL(seat->popup);
 
 	ds_window_destroy(wnd);
@@ -436,5 +478,8 @@
 	w1->dpos.y = 400;
 
-	PCUT_ASSERT_FALSE(called_cb);
+	/* New window gets focused event */
+	PCUT_ASSERT_TRUE(called_cb);
+
+	called_cb = false;
 
 	ds_seat_set_focus(seat, w0);
Index: uspace/srv/hid/display/test/window.c
===================================================================
--- uspace/srv/hid/display/test/window.c	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/srv/hid/display/test/window.c	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -104,4 +104,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -113,4 +114,7 @@
 
 	rc = ds_client_create(disp, NULL, NULL, &client);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, &seat);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -126,4 +130,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -136,4 +141,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	ds_window_t *rwindow;
@@ -152,4 +158,7 @@
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
+	rc = ds_seat_create(disp, &seat);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
 	display_wnd_params_init(&params);
 	params.rect.p0.x = params.rect.p0.y = 0;
@@ -157,4 +166,8 @@
 
 	rc = ds_window_create(client, &params, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* New window gets focused event */
+	rc = ds_client_get_event(client, &rwindow, &revent);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -174,4 +187,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -184,4 +198,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -196,4 +211,7 @@
 
 	rc = ds_client_create(disp, NULL, NULL, &client);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, &seat);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -242,4 +260,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -252,4 +271,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -264,4 +284,7 @@
 
 	rc = ds_client_create(disp, NULL, NULL, &client);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, &seat);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -284,4 +307,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -340,4 +364,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -353,4 +378,7 @@
 
 	rc = ds_client_create(disp, NULL, NULL, &client);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, &seat);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -597,4 +625,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
@@ -607,4 +636,5 @@
 	ds_display_t *disp;
 	ds_client_t *client;
+	ds_seat_t *seat;
 	ds_window_t *wnd;
 	display_wnd_params_t params;
@@ -618,4 +648,7 @@
 
 	rc = ds_client_create(disp, NULL, NULL, &client);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, &seat);
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
@@ -646,4 +679,5 @@
 
 	ds_window_destroy(wnd);
+	ds_seat_destroy(seat);
 	ds_client_destroy(client);
 	ds_display_destroy(disp);
Index: uspace/srv/hid/display/types/display/seat.h
===================================================================
--- uspace/srv/hid/display/types/display/seat.h	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/srv/hid/display/types/display/seat.h	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2019 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -48,4 +48,6 @@
 	/** Window this seat is focused on */
 	struct ds_window *focus;
+	/** This seat's popup window */
+	struct ds_window *popup;
 	/** Cursor selected by client */
 	struct ds_cursor *client_cursor;
Index: uspace/srv/hid/display/types/display/window.h
===================================================================
--- uspace/srv/hid/display/types/display/window.h	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/srv/hid/display/types/display/window.h	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2019 Jiri Svoboda
+ * Copyright (c) 2021 Jiri Svoboda
  * All rights reserved.
  *
@@ -39,4 +39,5 @@
 #include <adt/list.h>
 #include <display/event.h>
+#include <display/wndparams.h>
 #include <display/wndresize.h>
 #include <gfx/context.h>
@@ -92,5 +93,6 @@
 	/** Cursor set by client */
 	struct ds_cursor *cursor;
-
+	/** Window flags */
+	display_wnd_flags_t flags;
 	/** State */
 	ds_window_state_t state;
Index: uspace/srv/hid/display/window.c
===================================================================
--- uspace/srv/hid/display/window.c	(revision 6baab83ddb6d4e0ab2dc838329e4cf738b3f0d38)
+++ uspace/srv/hid/display/window.c	(revision b4b4dafec1d5fed1e8d2b84b501e3b97a9430fb0)
@@ -67,4 +67,5 @@
 {
 	ds_window_t *wnd = NULL;
+	ds_seat_t *seat;
 	gfx_context_t *dgc;
 	gfx_coord2_t dims;
@@ -116,4 +117,18 @@
 	wnd->gc = mem_gc_get_ctx(wnd->mgc);
 	wnd->cursor = wnd->display->cursor[dcurs_arrow];
+	wnd->flags = params->flags;
+
+	wnd->dpos.x = ((wnd->id - 1) & 1) * 400;
+	wnd->dpos.y = ((wnd->id - 1) & 2) / 2 * 300;
+
+	seat = ds_display_first_seat(client->display);
+
+	if ((params->flags & wndf_popup) != 0)
+		ds_seat_set_popup(seat, wnd);
+	else
+		ds_seat_set_focus(seat, wnd);
+
+	(void) ds_display_paint(wnd->display, NULL);
+
 	*rgc = wnd;
 	return EOK;
