Index: uspace/app/vterm/vterm.c
===================================================================
--- uspace/app/vterm/vterm.c	(revision aeb3037d16d12acc9017b38f10b453340424417d)
+++ uspace/app/vterm/vterm.c	(revision 06808543ddcf3db81aa4fd6bcb19218aa143260a)
@@ -56,5 +56,6 @@
 	}
 
-	window_resize(main_window, 0, 0, 648, 508, WINDOW_PLACEMENT_ANY);
+	window_resize(main_window, 0, 0, 648, 508, WINDOW_PLACEMENT_TOP |
+	    WINDOW_PLACEMENT_LEFT);
 	terminal_t *terminal_widget =
 	    create_terminal(window_root(main_window), NULL, 640, 480);
Index: uspace/lib/display/include/disp_srv.h
===================================================================
--- uspace/lib/display/include/disp_srv.h	(revision aeb3037d16d12acc9017b38f10b453340424417d)
+++ uspace/lib/display/include/disp_srv.h	(revision 06808543ddcf3db81aa4fd6bcb19218aa143260a)
@@ -59,4 +59,5 @@
 	errno_t (*window_resize_req)(void *, sysarg_t, display_wnd_rsztype_t,
 	    gfx_coord2_t *);
+	errno_t (*window_move)(void *, sysarg_t, gfx_coord2_t *);
 	errno_t (*window_resize)(void *, sysarg_t, gfx_coord2_t *, gfx_rect_t *);
 	errno_t (*get_event)(void *, sysarg_t *, display_wnd_ev_t *);
Index: uspace/lib/display/include/display.h
===================================================================
--- uspace/lib/display/include/display.h	(revision aeb3037d16d12acc9017b38f10b453340424417d)
+++ uspace/lib/display/include/display.h	(revision 06808543ddcf3db81aa4fd6bcb19218aa143260a)
@@ -56,4 +56,5 @@
 extern errno_t display_window_resize_req(display_window_t *,
     display_wnd_rsztype_t, gfx_coord2_t *);
+extern errno_t display_window_move(display_window_t *, gfx_coord2_t *);
 extern errno_t display_window_resize(display_window_t *,
     gfx_coord2_t *, gfx_rect_t *);
Index: uspace/lib/display/include/ipc/display.h
===================================================================
--- uspace/lib/display/include/ipc/display.h	(revision aeb3037d16d12acc9017b38f10b453340424417d)
+++ uspace/lib/display/include/ipc/display.h	(revision 06808543ddcf3db81aa4fd6bcb19218aa143260a)
@@ -42,4 +42,5 @@
 	DISPLAY_WINDOW_CREATE,
 	DISPLAY_WINDOW_DESTROY,
+	DISPLAY_WINDOW_MOVE,
 	DISPLAY_WINDOW_MOVE_REQ,
 	DISPLAY_WINDOW_RESIZE,
Index: uspace/lib/display/src/disp_srv.c
===================================================================
--- uspace/lib/display/src/disp_srv.c	(revision aeb3037d16d12acc9017b38f10b453340424417d)
+++ uspace/lib/display/src/disp_srv.c	(revision 06808543ddcf3db81aa4fd6bcb19218aa143260a)
@@ -149,15 +149,13 @@
 }
 
-static void display_window_resize_req_srv(display_srv_t *srv, ipc_call_t *icall)
-{
-	sysarg_t wnd_id;
-	ipc_call_t call;
-	display_wnd_rsztype_t rsztype;
-	gfx_coord2_t pos;
+static void display_window_move_srv(display_srv_t *srv, ipc_call_t *icall)
+{
+	sysarg_t wnd_id;
+	ipc_call_t call;
+	gfx_coord2_t dpos;
 	size_t size;
 	errno_t rc;
 
 	wnd_id = ipc_get_arg1(icall);
-	rsztype = (display_wnd_rsztype_t) ipc_get_arg2(icall);
 
 	if (!async_data_write_receive(&call, &size)) {
@@ -173,4 +171,45 @@
 	}
 
+	rc = async_data_write_finalize(&call, &dpos, size);
+	if (rc != EOK) {
+		async_answer_0(&call, rc);
+		async_answer_0(icall, rc);
+		return;
+	}
+
+	if (srv->ops->window_move == NULL) {
+		async_answer_0(icall, ENOTSUP);
+		return;
+	}
+
+	rc = srv->ops->window_move(srv->arg, wnd_id, &dpos);
+	async_answer_0(icall, rc);
+}
+
+
+static void display_window_resize_req_srv(display_srv_t *srv, ipc_call_t *icall)
+{
+	sysarg_t wnd_id;
+	ipc_call_t call;
+	display_wnd_rsztype_t rsztype;
+	gfx_coord2_t pos;
+	size_t size;
+	errno_t rc;
+
+	wnd_id = ipc_get_arg1(icall);
+	rsztype = (display_wnd_rsztype_t) ipc_get_arg2(icall);
+
+	if (!async_data_write_receive(&call, &size)) {
+		async_answer_0(&call, EREFUSED);
+		async_answer_0(icall, EREFUSED);
+		return;
+	}
+
+	if (size != sizeof(gfx_coord2_t)) {
+		async_answer_0(&call, EINVAL);
+		async_answer_0(icall, EINVAL);
+		return;
+	}
+
 	rc = async_data_write_finalize(&call, &pos, size);
 	if (rc != EOK) {
@@ -339,4 +378,7 @@
 		case DISPLAY_WINDOW_MOVE_REQ:
 			display_window_move_req_srv(srv, &call);
+			break;
+		case DISPLAY_WINDOW_MOVE:
+			display_window_move_srv(srv, &call);
 			break;
 		case DISPLAY_WINDOW_RESIZE_REQ:
Index: uspace/lib/display/src/display.c
===================================================================
--- uspace/lib/display/src/display.c	(revision aeb3037d16d12acc9017b38f10b453340424417d)
+++ uspace/lib/display/src/display.c	(revision 06808543ddcf3db81aa4fd6bcb19218aa143260a)
@@ -277,4 +277,38 @@
 }
 
+/** Move display window.
+ *
+ * Set new display position of a window. Display position determines where
+ * the origin of the window coordinate system lies. Note that the top left
+ * corner of the window need not coincide with the window's 0,0 point.
+ *
+ * @param window Window
+ * @param dpos New display position
+ * @return EOK on success or an error code
+ */
+errno_t display_window_move(display_window_t *window, gfx_coord2_t *dpos)
+{
+	async_exch_t *exch;
+	aid_t req;
+	ipc_call_t answer;
+	errno_t rc;
+
+	exch = async_exchange_begin(window->display->sess);
+	req = async_send_1(exch, DISPLAY_WINDOW_MOVE, window->id, &answer);
+	rc = async_data_write_start(exch, dpos, sizeof (gfx_coord2_t));
+	async_exchange_end(exch);
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	async_wait_for(req, &rc);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
+
 /** Request a window resize.
  *
Index: uspace/lib/display/test/display.c
===================================================================
--- uspace/lib/display/test/display.c	(revision aeb3037d16d12acc9017b38f10b453340424417d)
+++ uspace/lib/display/test/display.c	(revision 06808543ddcf3db81aa4fd6bcb19218aa143260a)
@@ -57,4 +57,5 @@
 static errno_t test_window_destroy(void *, sysarg_t);
 static errno_t test_window_move_req(void *, sysarg_t, gfx_coord2_t *);
+static errno_t test_window_move(void *, sysarg_t, gfx_coord2_t *);
 static errno_t test_window_resize_req(void *, sysarg_t, display_wnd_rsztype_t,
     gfx_coord2_t *);
@@ -70,4 +71,5 @@
 	.window_destroy = test_window_destroy,
 	.window_move_req = test_window_move_req,
+	.window_move = test_window_move,
 	.window_resize_req = test_window_resize_req,
 	.window_resize = test_window_resize,
@@ -106,4 +108,8 @@
 	sysarg_t move_req_wnd_id;
 	gfx_coord2_t move_req_pos;
+
+	bool window_move_called;
+	sysarg_t move_wnd_id;
+	gfx_coord2_t move_dpos;
 
 	bool window_resize_req_called;
@@ -422,4 +428,112 @@
 	PCUT_ASSERT_INT_EQUALS(pos.x, resp.move_req_pos.x);
 	PCUT_ASSERT_INT_EQUALS(pos.y, resp.move_req_pos.y);
+
+	display_window_destroy(wnd);
+	display_close(disp);
+	rc = loc_service_unregister(sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+}
+
+/** display_window_move() with server returning error response works. */
+PCUT_TEST(window_move_failure)
+{
+	errno_t rc;
+	service_id_t sid;
+	display_t *disp = NULL;
+	display_wnd_params_t params;
+	display_window_t *wnd;
+	gfx_coord2_t dpos;
+	test_response_t resp;
+
+	async_set_fallback_port_handler(test_display_conn, &resp);
+
+	// FIXME This causes this test to be non-reentrant!
+	rc = loc_server_register(test_display_server);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = loc_service_register(test_display_svc, &sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = display_open(test_display_svc, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(disp);
+
+	resp.rc = EOK;
+	display_wnd_params_init(&params);
+	params.rect.p0.x = 0;
+	params.rect.p0.y = 0;
+	params.rect.p0.x = 100;
+	params.rect.p0.y = 100;
+
+	rc = display_window_create(disp, &params, &test_display_wnd_cb,
+	    (void *) &resp, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(wnd);
+
+	resp.rc = EIO;
+	resp.window_move_called = false;
+	dpos.x = 11;
+	dpos.y = 12;
+
+	rc = display_window_move(wnd, &dpos);
+	PCUT_ASSERT_TRUE(resp.window_move_called);
+	PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
+	PCUT_ASSERT_INT_EQUALS(wnd->id, resp.move_wnd_id);
+	PCUT_ASSERT_INT_EQUALS(dpos.x, resp.move_dpos.x);
+	PCUT_ASSERT_INT_EQUALS(dpos.y, resp.move_dpos.y);
+
+	display_window_destroy(wnd);
+	display_close(disp);
+	rc = loc_service_unregister(sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+}
+
+/** display_window_move() with server returning success response works. */
+PCUT_TEST(window_move_success)
+{
+	errno_t rc;
+	service_id_t sid;
+	display_t *disp = NULL;
+	display_wnd_params_t params;
+	display_window_t *wnd;
+	gfx_coord2_t dpos;
+	test_response_t resp;
+
+	async_set_fallback_port_handler(test_display_conn, &resp);
+
+	// FIXME This causes this test to be non-reentrant!
+	rc = loc_server_register(test_display_server);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = loc_service_register(test_display_svc, &sid);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = display_open(test_display_svc, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(disp);
+
+	resp.rc = EOK;
+	display_wnd_params_init(&params);
+	params.rect.p0.x = 0;
+	params.rect.p0.y = 0;
+	params.rect.p0.x = 100;
+	params.rect.p0.y = 100;
+
+	rc = display_window_create(disp, &params, &test_display_wnd_cb,
+	    (void *) &resp, &wnd);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_NOT_NULL(wnd);
+
+	resp.rc = EOK;
+	resp.window_move_called = false;
+	dpos.x = 11;
+	dpos.y = 12;
+
+	rc = display_window_move(wnd, &dpos);
+	PCUT_ASSERT_TRUE(resp.window_move_called);
+	PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
+	PCUT_ASSERT_INT_EQUALS(wnd->id, resp.move_wnd_id);
+	PCUT_ASSERT_INT_EQUALS(dpos.x, resp.move_dpos.x);
+	PCUT_ASSERT_INT_EQUALS(dpos.y, resp.move_dpos.y);
 
 	display_window_destroy(wnd);
@@ -1352,4 +1466,14 @@
 }
 
+static errno_t test_window_move(void *arg, sysarg_t wnd_id, gfx_coord2_t *dpos)
+{
+	test_response_t *resp = (test_response_t *) arg;
+
+	resp->window_move_called = true;
+	resp->move_wnd_id = wnd_id;
+	resp->move_dpos = *dpos;
+	return resp->rc;
+}
+
 static errno_t test_window_resize_req(void *arg, sysarg_t wnd_id,
     display_wnd_rsztype_t rsztype, gfx_coord2_t *pos)
Index: uspace/lib/gui/window.c
===================================================================
--- uspace/lib/gui/window.c	(revision aeb3037d16d12acc9017b38f10b453340424417d)
+++ uspace/lib/gui/window.c	(revision 06808543ddcf3db81aa4fd6bcb19218aa143260a)
@@ -375,4 +375,7 @@
 	gfx_bitmap_t *new_bitmap = NULL;
 	gfx_coord2_t offs;
+	gfx_coord2_t dpos;
+	display_info_t dinfo;
+	gfx_rect_t drect;
 	gfx_rect_t nrect;
 	errno_t rc;
@@ -460,13 +463,43 @@
 
 		surface_destroy(new_surface);
-	} else {
-		if (old_bitmap != NULL)
-			gfx_bitmap_destroy(old_bitmap);
-		/* Deallocate old surface. */
-		if (old_surface)
-			surface_destroy(old_surface);
-
-		(void) gfx_bitmap_render(win->bitmap, NULL, NULL);
-	}
+		return;
+	}
+
+	if (old_bitmap != NULL)
+		gfx_bitmap_destroy(old_bitmap);
+	/* Deallocate old surface. */
+	if (old_surface)
+		surface_destroy(old_surface);
+
+	if (placement_flags != WINDOW_PLACEMENT_ANY) {
+		dpos.x = 0;
+		dpos.y = 0;
+
+		rc = display_get_info(win->display, &dinfo);
+		if (rc != EOK) {
+			(void) gfx_bitmap_render(win->bitmap, NULL, NULL);
+			return;
+		}
+
+		drect = dinfo.rect;
+
+		if (placement_flags & WINDOW_PLACEMENT_LEFT)
+			dpos.x = drect.p0.x;
+		else if (placement_flags & WINDOW_PLACEMENT_CENTER_X)
+			dpos.x = (drect.p0.x + drect.p0.y - width) / 2;
+		else
+			dpos.x = drect.p1.x - width;
+
+		if (placement_flags & WINDOW_PLACEMENT_TOP)
+			dpos.y = drect.p0.y;
+		else if (placement_flags & WINDOW_PLACEMENT_CENTER_Y)
+			dpos.y = (drect.p0.y + drect.p1.y - height) / 2;
+		else
+			dpos.y = drect.p1.y - height;
+
+		(void) display_window_move(win->dwindow, &dpos);
+	}
+
+	(void) gfx_bitmap_render(win->bitmap, NULL, NULL);
 }
 
Index: uspace/srv/hid/display/dsops.c
===================================================================
--- uspace/srv/hid/display/dsops.c	(revision aeb3037d16d12acc9017b38f10b453340424417d)
+++ uspace/srv/hid/display/dsops.c	(revision 06808543ddcf3db81aa4fd6bcb19218aa143260a)
@@ -47,4 +47,5 @@
 static errno_t disp_window_destroy(void *, sysarg_t);
 static errno_t disp_window_move_req(void *, sysarg_t, gfx_coord2_t *);
+static errno_t disp_window_move(void *, sysarg_t, gfx_coord2_t *);
 static errno_t disp_window_resize_req(void *, sysarg_t,
     display_wnd_rsztype_t, gfx_coord2_t *);
@@ -58,4 +59,5 @@
 	.window_destroy = disp_window_destroy,
 	.window_move_req = disp_window_move_req,
+	.window_move = disp_window_move,
 	.window_resize_req = disp_window_resize_req,
 	.window_resize = disp_window_resize,
@@ -124,4 +126,18 @@
 }
 
+static errno_t disp_window_move(void *arg, sysarg_t wnd_id, gfx_coord2_t *pos)
+{
+	ds_client_t *client = (ds_client_t *) arg;
+	ds_window_t *wnd;
+
+	wnd = ds_client_find_window(client, wnd_id);
+	if (wnd == NULL)
+		return ENOENT;
+
+	log_msg(LVL_NOTE, LVL_DEBUG, "disp_window_move()");
+	ds_window_move(wnd, pos);
+	return EOK;
+}
+
 static errno_t disp_window_resize_req(void *arg, sysarg_t wnd_id,
     display_wnd_rsztype_t rsztype, gfx_coord2_t *pos)
Index: uspace/srv/hid/display/window.c
===================================================================
--- uspace/srv/hid/display/window.c	(revision aeb3037d16d12acc9017b38f10b453340424417d)
+++ uspace/srv/hid/display/window.c	(revision 06808543ddcf3db81aa4fd6bcb19218aa143260a)
@@ -346,4 +346,374 @@
 }
 
+/** Bring window to top.
+ *
+ * @param wnd Window
+ */
+void ds_window_bring_to_top(ds_window_t *wnd)
+{
+	ds_display_t *disp = wnd->display;
+
+	ds_display_remove_window(wnd);
+	ds_display_add_window(disp, wnd);
+}
+
+/** Get generic graphic context from window.
+ *
+ * @param wnd Window
+ * @return Graphic context
+ */
+gfx_context_t *ds_window_get_ctx(ds_window_t *wnd)
+{
+	return wnd->gc;
+}
+
+/** Paint a window using its backing bitmap.
+ *
+ * @param wnd Window to paint
+ * @param rect Display rectangle to paint to
+ * @return EOK on success or an error code
+ */
+errno_t ds_window_paint(ds_window_t *wnd, gfx_rect_t *rect)
+{
+	gfx_rect_t srect;
+	gfx_rect_t *brect;
+	gfx_rect_t crect;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_paint");
+
+	if (rect != NULL) {
+		gfx_rect_rtranslate(&wnd->dpos, rect, &srect);
+
+		/* Determine if we have anything to do */
+		gfx_rect_clip(&srect, &wnd->rect, &crect);
+		if (gfx_rect_is_empty(&crect))
+			return EOK;
+
+		brect = &srect;
+	} else {
+		brect = NULL;
+	}
+
+	/* This can happen in unit tests */
+	if (wnd->bitmap == NULL)
+		return EOK;
+
+	return gfx_bitmap_render(wnd->bitmap, brect, &wnd->dpos);
+}
+
+/** Start moving a window by mouse drag.
+ *
+ * @param wnd Window
+ * @param event Button press event
+ */
+static void ds_window_start_move(ds_window_t *wnd, pos_event_t *event)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_start_move (%d, %d)",
+	    (int) event->hpos, (int) event->vpos);
+
+	if (wnd->state != dsw_idle)
+		return;
+
+	wnd->orig_pos.x = event->hpos;
+	wnd->orig_pos.y = event->vpos;
+	wnd->state = dsw_moving;
+}
+
+/** Finish moving a window by mouse drag.
+ *
+ * @param wnd Window
+ * @param event Button release event
+ */
+static void ds_window_finish_move(ds_window_t *wnd, pos_event_t *event)
+{
+	gfx_coord2_t pos;
+	gfx_coord2_t dmove;
+	gfx_coord2_t nwpos;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_move (%d, %d)",
+	    (int) event->hpos, (int) event->vpos);
+
+	if (wnd->state != dsw_moving)
+		return;
+
+	pos.x = event->hpos;
+	pos.y = event->vpos;
+	gfx_coord2_subtract(&pos, &wnd->orig_pos, &dmove);
+
+	gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
+	wnd->dpos = nwpos;
+	wnd->state = dsw_idle;
+
+	(void) ds_display_paint(wnd->display, NULL);
+}
+
+/** Update window position when moving by mouse drag.
+ *
+ * @param wnd Window
+ * @param event Position update event
+ */
+static void ds_window_update_move(ds_window_t *wnd, pos_event_t *event)
+{
+	gfx_coord2_t pos;
+	gfx_coord2_t dmove;
+	gfx_coord2_t nwpos;
+	gfx_rect_t drect;
+	gfx_color_t *color;
+	gfx_context_t *gc;
+	errno_t rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_move (%d, %d)",
+	    (int) event->hpos, (int) event->vpos);
+
+	if (wnd->state != dsw_moving)
+		return;
+
+	gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
+
+	gc = ds_display_get_gc(wnd->display); // XXX
+	if (gc != NULL) {
+		gfx_set_color(gc, wnd->display->bg_color);
+		gfx_fill_rect(gc, &drect);
+	}
+
+	pos.x = event->hpos;
+	pos.y = event->vpos;
+	gfx_coord2_subtract(&pos, &wnd->orig_pos, &dmove);
+
+	gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
+	gfx_rect_translate(&nwpos, &wnd->rect, &drect);
+
+	wnd->orig_pos = pos;
+	wnd->dpos = nwpos;
+
+	rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
+	if (rc != EOK)
+		return;
+
+	gc = ds_display_get_gc(wnd->display); // XXX
+	if (gc != NULL) {
+		gfx_set_color(gc, color);
+		gfx_fill_rect(gc, &drect);
+	}
+
+	gfx_color_delete(color);
+}
+
+/** Finish resizing a window by mouse drag.
+ *
+ * @param wnd Window
+ * @param event Button release event
+ */
+static void ds_window_finish_resize(ds_window_t *wnd, pos_event_t *event)
+{
+	gfx_coord2_t pos;
+	gfx_coord2_t dresize;
+	gfx_rect_t nrect;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_resize (%d, %d)",
+	    (int) event->hpos, (int) event->vpos);
+
+	if (wnd->state != dsw_resizing)
+		return;
+
+	(void) ds_display_paint(wnd->display, NULL);
+
+	pos.x = event->hpos;
+	pos.y = event->vpos;
+	gfx_coord2_subtract(&pos, &wnd->orig_pos, &dresize);
+
+	/* Compute new rectangle */
+	ds_window_calc_resize(wnd, &dresize, &nrect);
+
+	wnd->state = dsw_idle;
+	ds_client_post_resize_event(wnd->client, wnd, &nrect);
+}
+
+/** Update window position when resizing by mouse drag.
+ *
+ * @param wnd Window
+ * @param event Position update event
+ */
+static void ds_window_update_resize(ds_window_t *wnd, pos_event_t *event)
+{
+	gfx_coord2_t pos;
+	gfx_coord2_t dresize;
+	gfx_rect_t nrect;
+	gfx_rect_t drect;
+	gfx_color_t *color;
+	gfx_context_t *gc;
+	errno_t rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_resize (%d, %d)",
+	    (int) event->hpos, (int) event->vpos);
+
+	if (wnd->state != dsw_resizing)
+		return;
+
+	gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
+
+	gc = ds_display_get_gc(wnd->display); // XXX
+	if (gc != NULL) {
+		gfx_set_color(gc, wnd->display->bg_color);
+		gfx_fill_rect(gc, &drect);
+	}
+
+	pos.x = event->hpos;
+	pos.y = event->vpos;
+	gfx_coord2_subtract(&pos, &wnd->orig_pos, &dresize);
+
+	ds_window_calc_resize(wnd, &dresize, &nrect);
+	gfx_rect_translate(&wnd->dpos, &nrect, &drect);
+
+	rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
+	if (rc != EOK)
+		return;
+
+	gc = ds_display_get_gc(wnd->display); // XXX
+	if (gc != NULL) {
+		gfx_set_color(gc, color);
+		gfx_fill_rect(gc, &drect);
+	}
+
+	gfx_color_delete(color);
+}
+
+/** Post keyboard event to window.
+ *
+ * @param wnd Window
+ * @param event Event
+ *
+ * @return EOK on success or an error code
+ */
+errno_t ds_window_post_kbd_event(ds_window_t *wnd, kbd_event_t *event)
+{
+	bool alt_or_shift;
+
+	alt_or_shift = event->mods & (KM_SHIFT | KM_ALT);
+
+	if (event->type == KEY_PRESS && alt_or_shift && event->key == KC_F4) {
+		/* On Alt-F4 or Shift-F4 send close event to the window */
+		ds_client_post_close_event(wnd->client, wnd);
+		return EOK;
+	}
+
+	return ds_client_post_kbd_event(wnd->client, wnd, event);
+}
+
+/** Post position event to window.
+ *
+ * @param wnd Window
+ * @param event Position event
+ */
+errno_t ds_window_post_pos_event(ds_window_t *wnd, pos_event_t *event)
+{
+	pos_event_t tevent;
+	gfx_coord2_t pos;
+	gfx_rect_t drect;
+	bool inside;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG,
+	    "ds_window_post_pos_event type=%d pos=%d,%d\n", event->type,
+	    (int) event->hpos, (int) event->vpos);
+
+	pos.x = event->hpos;
+	pos.y = event->vpos;
+	gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
+	inside = gfx_pix_inside_rect(&pos, &drect);
+
+	if (event->type == POS_PRESS && event->btn_num == 2 && inside)
+		ds_window_start_move(wnd, event);
+
+	if (event->type == POS_RELEASE) {
+		ds_window_finish_move(wnd, event);
+		ds_window_finish_resize(wnd, event);
+	}
+
+	if (event->type == POS_UPDATE) {
+		ds_window_update_move(wnd, event);
+		ds_window_update_resize(wnd, event);
+	}
+
+	/* Transform event coordinates to window-local */
+	tevent = *event;
+	tevent.hpos -= wnd->dpos.x;
+	tevent.vpos -= wnd->dpos.y;
+
+	return ds_client_post_pos_event(wnd->client, wnd, &tevent);
+}
+
+/** Post focus event to window.
+ *
+ * @param wnd Window
+ */
+errno_t ds_window_post_focus_event(ds_window_t *wnd)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_post_focus_event\n");
+
+	return ds_client_post_focus_event(wnd->client, wnd);
+}
+
+/** Post unfocus event to window.
+ *
+ * @param wnd Window
+ */
+errno_t ds_window_post_unfocus_event(ds_window_t *wnd)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_post_unfocus_event\n");
+
+	return ds_client_post_unfocus_event(wnd->client, wnd);
+}
+
+/** Start moving a window, detected by client.
+ *
+ * @param wnd Window
+ * @param pos Position where the pointer was when the move started
+ *            relative to the window
+ * @param event Button press event
+ */
+void ds_window_move_req(ds_window_t *wnd, gfx_coord2_t *pos)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_move_req (%d, %d)",
+	    (int) pos->x, (int) pos->y);
+
+	if (wnd->state != dsw_idle)
+		return;
+
+	gfx_coord2_add(&wnd->dpos, pos, &wnd->orig_pos);
+	wnd->state = dsw_moving;
+}
+
+/** Move window.
+ *
+ * @param wnd Window
+ */
+void ds_window_move(ds_window_t *wnd, gfx_coord2_t *dpos)
+{
+	wnd->dpos = *dpos;
+	(void) ds_display_paint(wnd->display, NULL);
+}
+
+/** Start resizing a window, detected by client.
+ *
+ * @param wnd Window
+ * @param rsztype Resize type (which part of window is being dragged)
+ * @param pos Position where the pointer was when the resize started
+ *            relative to the window
+ * @param event Button press event
+ */
+void ds_window_resize_req(ds_window_t *wnd, display_wnd_rsztype_t rsztype,
+    gfx_coord2_t *pos)
+{
+	log_msg(LOG_DEFAULT, LVL_NOTE, "ds_window_resize_req (%d, %d, %d)",
+	    (int) rsztype, (int) pos->x, (int) pos->y);
+
+	if (wnd->state != dsw_idle)
+		return;
+
+	gfx_coord2_add(&wnd->dpos, pos, &wnd->orig_pos);
+	wnd->state = dsw_resizing;
+	wnd->rsztype = rsztype;
+}
+
 /** Resize window.
  *
@@ -400,364 +770,4 @@
 }
 
-/** Bring window to top.
- *
- * @param wnd Window
- */
-void ds_window_bring_to_top(ds_window_t *wnd)
-{
-	ds_display_t *disp = wnd->display;
-
-	ds_display_remove_window(wnd);
-	ds_display_add_window(disp, wnd);
-}
-
-/** Get generic graphic context from window.
- *
- * @param wnd Window
- * @return Graphic context
- */
-gfx_context_t *ds_window_get_ctx(ds_window_t *wnd)
-{
-	return wnd->gc;
-}
-
-/** Paint a window using its backing bitmap.
- *
- * @param wnd Window to paint
- * @param rect Display rectangle to paint to
- * @return EOK on success or an error code
- */
-errno_t ds_window_paint(ds_window_t *wnd, gfx_rect_t *rect)
-{
-	gfx_rect_t srect;
-	gfx_rect_t *brect;
-	gfx_rect_t crect;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_paint");
-
-	if (rect != NULL) {
-		gfx_rect_rtranslate(&wnd->dpos, rect, &srect);
-
-		/* Determine if we have anything to do */
-		gfx_rect_clip(&srect, &wnd->rect, &crect);
-		if (gfx_rect_is_empty(&crect))
-			return EOK;
-
-		brect = &srect;
-	} else {
-		brect = NULL;
-	}
-
-	/* This can happen in unit tests */
-	if (wnd->bitmap == NULL)
-		return EOK;
-
-	return gfx_bitmap_render(wnd->bitmap, brect, &wnd->dpos);
-}
-
-/** Start moving a window by mouse drag.
- *
- * @param wnd Window
- * @param event Button press event
- */
-static void ds_window_start_move(ds_window_t *wnd, pos_event_t *event)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_start_move (%d, %d)",
-	    (int) event->hpos, (int) event->vpos);
-
-	if (wnd->state != dsw_idle)
-		return;
-
-	wnd->orig_pos.x = event->hpos;
-	wnd->orig_pos.y = event->vpos;
-	wnd->state = dsw_moving;
-}
-
-/** Finish moving a window by mouse drag.
- *
- * @param wnd Window
- * @param event Button release event
- */
-static void ds_window_finish_move(ds_window_t *wnd, pos_event_t *event)
-{
-	gfx_coord2_t pos;
-	gfx_coord2_t dmove;
-	gfx_coord2_t nwpos;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_move (%d, %d)",
-	    (int) event->hpos, (int) event->vpos);
-
-	if (wnd->state != dsw_moving)
-		return;
-
-	pos.x = event->hpos;
-	pos.y = event->vpos;
-	gfx_coord2_subtract(&pos, &wnd->orig_pos, &dmove);
-
-	gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
-	wnd->dpos = nwpos;
-	wnd->state = dsw_idle;
-
-	(void) ds_display_paint(wnd->display, NULL);
-}
-
-/** Update window position when moving by mouse drag.
- *
- * @param wnd Window
- * @param event Position update event
- */
-static void ds_window_update_move(ds_window_t *wnd, pos_event_t *event)
-{
-	gfx_coord2_t pos;
-	gfx_coord2_t dmove;
-	gfx_coord2_t nwpos;
-	gfx_rect_t drect;
-	gfx_color_t *color;
-	gfx_context_t *gc;
-	errno_t rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_move (%d, %d)",
-	    (int) event->hpos, (int) event->vpos);
-
-	if (wnd->state != dsw_moving)
-		return;
-
-	gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
-
-	gc = ds_display_get_gc(wnd->display); // XXX
-	if (gc != NULL) {
-		gfx_set_color(gc, wnd->display->bg_color);
-		gfx_fill_rect(gc, &drect);
-	}
-
-	pos.x = event->hpos;
-	pos.y = event->vpos;
-	gfx_coord2_subtract(&pos, &wnd->orig_pos, &dmove);
-
-	gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
-	gfx_rect_translate(&nwpos, &wnd->rect, &drect);
-
-	wnd->orig_pos = pos;
-	wnd->dpos = nwpos;
-
-	rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
-	if (rc != EOK)
-		return;
-
-	gc = ds_display_get_gc(wnd->display); // XXX
-	if (gc != NULL) {
-		gfx_set_color(gc, color);
-		gfx_fill_rect(gc, &drect);
-	}
-
-	gfx_color_delete(color);
-}
-
-/** Finish resizing a window by mouse drag.
- *
- * @param wnd Window
- * @param event Button release event
- */
-static void ds_window_finish_resize(ds_window_t *wnd, pos_event_t *event)
-{
-	gfx_coord2_t pos;
-	gfx_coord2_t dresize;
-	gfx_rect_t nrect;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_resize (%d, %d)",
-	    (int) event->hpos, (int) event->vpos);
-
-	if (wnd->state != dsw_resizing)
-		return;
-
-	(void) ds_display_paint(wnd->display, NULL);
-
-	pos.x = event->hpos;
-	pos.y = event->vpos;
-	gfx_coord2_subtract(&pos, &wnd->orig_pos, &dresize);
-
-	/* Compute new rectangle */
-	ds_window_calc_resize(wnd, &dresize, &nrect);
-
-	wnd->state = dsw_idle;
-	ds_client_post_resize_event(wnd->client, wnd, &nrect);
-}
-
-/** Update window position when resizing by mouse drag.
- *
- * @param wnd Window
- * @param event Position update event
- */
-static void ds_window_update_resize(ds_window_t *wnd, pos_event_t *event)
-{
-	gfx_coord2_t pos;
-	gfx_coord2_t dresize;
-	gfx_rect_t nrect;
-	gfx_rect_t drect;
-	gfx_color_t *color;
-	gfx_context_t *gc;
-	errno_t rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_resize (%d, %d)",
-	    (int) event->hpos, (int) event->vpos);
-
-	if (wnd->state != dsw_resizing)
-		return;
-
-	gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
-
-	gc = ds_display_get_gc(wnd->display); // XXX
-	if (gc != NULL) {
-		gfx_set_color(gc, wnd->display->bg_color);
-		gfx_fill_rect(gc, &drect);
-	}
-
-	pos.x = event->hpos;
-	pos.y = event->vpos;
-	gfx_coord2_subtract(&pos, &wnd->orig_pos, &dresize);
-
-	ds_window_calc_resize(wnd, &dresize, &nrect);
-	gfx_rect_translate(&wnd->dpos, &nrect, &drect);
-
-	rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
-	if (rc != EOK)
-		return;
-
-	gc = ds_display_get_gc(wnd->display); // XXX
-	if (gc != NULL) {
-		gfx_set_color(gc, color);
-		gfx_fill_rect(gc, &drect);
-	}
-
-	gfx_color_delete(color);
-}
-
-/** Post keyboard event to window.
- *
- * @param wnd Window
- * @param event Event
- *
- * @return EOK on success or an error code
- */
-errno_t ds_window_post_kbd_event(ds_window_t *wnd, kbd_event_t *event)
-{
-	bool alt_or_shift;
-
-	alt_or_shift = event->mods & (KM_SHIFT | KM_ALT);
-
-	if (event->type == KEY_PRESS && alt_or_shift && event->key == KC_F4) {
-		/* On Alt-F4 or Shift-F4 send close event to the window */
-		ds_client_post_close_event(wnd->client, wnd);
-		return EOK;
-	}
-
-	return ds_client_post_kbd_event(wnd->client, wnd, event);
-}
-
-/** Post position event to window.
- *
- * @param wnd Window
- * @param event Position event
- */
-errno_t ds_window_post_pos_event(ds_window_t *wnd, pos_event_t *event)
-{
-	pos_event_t tevent;
-	gfx_coord2_t pos;
-	gfx_rect_t drect;
-	bool inside;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG,
-	    "ds_window_post_pos_event type=%d pos=%d,%d\n", event->type,
-	    (int) event->hpos, (int) event->vpos);
-
-	pos.x = event->hpos;
-	pos.y = event->vpos;
-	gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
-	inside = gfx_pix_inside_rect(&pos, &drect);
-
-	if (event->type == POS_PRESS && event->btn_num == 2 && inside)
-		ds_window_start_move(wnd, event);
-
-	if (event->type == POS_RELEASE) {
-		ds_window_finish_move(wnd, event);
-		ds_window_finish_resize(wnd, event);
-	}
-
-	if (event->type == POS_UPDATE) {
-		ds_window_update_move(wnd, event);
-		ds_window_update_resize(wnd, event);
-	}
-
-	/* Transform event coordinates to window-local */
-	tevent = *event;
-	tevent.hpos -= wnd->dpos.x;
-	tevent.vpos -= wnd->dpos.y;
-
-	return ds_client_post_pos_event(wnd->client, wnd, &tevent);
-}
-
-/** Post focus event to window.
- *
- * @param wnd Window
- */
-errno_t ds_window_post_focus_event(ds_window_t *wnd)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_post_focus_event\n");
-
-	return ds_client_post_focus_event(wnd->client, wnd);
-}
-
-/** Post unfocus event to window.
- *
- * @param wnd Window
- */
-errno_t ds_window_post_unfocus_event(ds_window_t *wnd)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_post_unfocus_event\n");
-
-	return ds_client_post_unfocus_event(wnd->client, wnd);
-}
-
-/** Start moving a window, detected by client.
- *
- * @param wnd Window
- * @param pos Position where the pointer was when the move started
- *            relative to the window
- * @param event Button press event
- */
-void ds_window_move_req(ds_window_t *wnd, gfx_coord2_t *pos)
-{
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_move_req (%d, %d)",
-	    (int) pos->x, (int) pos->y);
-
-	if (wnd->state != dsw_idle)
-		return;
-
-	gfx_coord2_add(&wnd->dpos, pos, &wnd->orig_pos);
-	wnd->state = dsw_moving;
-}
-
-/** Start resizing a window, detected by client.
- *
- * @param wnd Window
- * @param rsztype Resize type (which part of window is being dragged)
- * @param pos Position where the pointer was when the resize started
- *            relative to the window
- * @param event Button press event
- */
-void ds_window_resize_req(ds_window_t *wnd, display_wnd_rsztype_t rsztype,
-    gfx_coord2_t *pos)
-{
-	log_msg(LOG_DEFAULT, LVL_NOTE, "ds_window_resize_req (%d, %d, %d)",
-	    (int) rsztype, (int) pos->x, (int) pos->y);
-
-	if (wnd->state != dsw_idle)
-		return;
-
-	gfx_coord2_add(&wnd->dpos, pos, &wnd->orig_pos);
-	wnd->state = dsw_resizing;
-	wnd->rsztype = rsztype;
-}
-
 /** Compute new window rectangle after resize operation.
  *
Index: uspace/srv/hid/display/window.h
===================================================================
--- uspace/srv/hid/display/window.h	(revision aeb3037d16d12acc9017b38f10b453340424417d)
+++ uspace/srv/hid/display/window.h	(revision 06808543ddcf3db81aa4fd6bcb19218aa143260a)
@@ -52,5 +52,4 @@
     ds_window_t **);
 extern void ds_window_destroy(ds_window_t *);
-extern errno_t ds_window_resize(ds_window_t *, gfx_coord2_t *, gfx_rect_t *);
 extern void ds_window_bring_to_top(ds_window_t *);
 extern gfx_context_t *ds_window_get_ctx(ds_window_t *);
@@ -60,8 +59,10 @@
 extern errno_t ds_window_post_focus_event(ds_window_t *);
 extern errno_t ds_window_post_unfocus_event(ds_window_t *);
-extern void ds_window_move_req(ds_window_t *wnd, gfx_coord2_t *);
-extern void ds_window_resize_req(ds_window_t *wnd, display_wnd_rsztype_t,
+extern void ds_window_move_req(ds_window_t *, gfx_coord2_t *);
+extern void ds_window_move(ds_window_t *, gfx_coord2_t *);
+extern void ds_window_resize_req(ds_window_t *, display_wnd_rsztype_t,
     gfx_coord2_t *);
-extern void ds_window_calc_resize(ds_window_t *wnd, gfx_coord2_t *,
+extern errno_t ds_window_resize(ds_window_t *, gfx_coord2_t *, gfx_rect_t *);
+extern void ds_window_calc_resize(ds_window_t *, gfx_coord2_t *,
     gfx_rect_t *);
 
