Index: uspace/lib/gfx/include/gfx/coord.h
===================================================================
--- uspace/lib/gfx/include/gfx/coord.h	(revision d70e7b7bcaa004700e0af401f3e5b48e47f018c1)
+++ uspace/lib/gfx/include/gfx/coord.h	(revision 6301a24fb081993e0e1d27b0a61a9bab72fca055)
@@ -54,4 +54,5 @@
 extern void gfx_rect_dims(gfx_rect_t *, gfx_coord2_t *);
 extern bool gfx_rect_is_empty(gfx_rect_t *);
+extern bool gfx_rect_is_incident(gfx_rect_t *, gfx_rect_t *);
 extern bool gfx_pix_inside_rect(gfx_coord2_t *, gfx_rect_t *);
 
Index: uspace/lib/gfx/src/coord.c
===================================================================
--- uspace/lib/gfx/src/coord.c	(revision d70e7b7bcaa004700e0af401f3e5b48e47f018c1)
+++ uspace/lib/gfx/src/coord.c	(revision 6301a24fb081993e0e1d27b0a61a9bab72fca055)
@@ -37,4 +37,5 @@
 #include <macros.h>
 #include <stdbool.h>
+#include <stddef.h>
 
 /** Add two vectors.
@@ -192,8 +193,8 @@
  * If the two rectangles do not intersect, the result will be an empty
  * rectangle (check with gfx_rect_is_empty()). The resulting rectangle
- * is always sorted.
+ * is always sorted. If @a clip is NULL, no clipping is performed.
  *
  * @param rect Source rectangle
- * @param clip Clipping rectangle
+ * @param clip Clipping rectangle or @c NULL
  * @param dest Place to store clipped rectangle
  */
@@ -201,4 +202,9 @@
 {
 	gfx_rect_t srect, sclip;
+
+	if (clip == NULL) {
+		*dest = *rect;
+		return;
+	}
 
 	gfx_rect_points_sort(rect, &srect);
@@ -235,4 +241,18 @@
 }
 
+/** Determine if two rectangles share any pixels
+ *
+ * @param a First rectangle
+ * @param b Second rectangle
+ * @return @c true iff rectangles share any pixels
+ */
+bool gfx_rect_is_incident(gfx_rect_t *a, gfx_rect_t *b)
+{
+	gfx_rect_t r;
+
+	gfx_rect_clip(a, b, &r);
+	return !gfx_rect_is_empty(&r);
+}
+
 /** Get rectangle dimensions.
  *
Index: uspace/lib/gfx/test/coord.c
===================================================================
--- uspace/lib/gfx/test/coord.c	(revision d70e7b7bcaa004700e0af401f3e5b48e47f018c1)
+++ uspace/lib/gfx/test/coord.c	(revision 6301a24fb081993e0e1d27b0a61a9bab72fca055)
@@ -560,4 +560,22 @@
 }
 
+/** Clip rectangle with no clipping rectangle */
+PCUT_TEST(rect_clip_rect_noclip)
+{
+	gfx_rect_t rect;
+	gfx_rect_t dest;
+
+	rect.p0.x = 1;
+	rect.p0.y = 2;
+	rect.p1.x = 3;
+	rect.p1.y = 4;
+
+	gfx_rect_clip(&rect, NULL, &dest);
+	PCUT_ASSERT_INT_EQUALS(rect.p0.x, dest.p0.x);
+	PCUT_ASSERT_INT_EQUALS(rect.p0.y, dest.p0.y);
+	PCUT_ASSERT_INT_EQUALS(rect.p1.x, dest.p1.x);
+	PCUT_ASSERT_INT_EQUALS(rect.p1.y, dest.p1.y);
+}
+
 /** Sort span points that are already sorted should produde indentical points */
 PCUT_TEST(rect_points_sort_sorted)
@@ -638,5 +656,5 @@
 }
 
-/** gfx_rect_is_empty for staright non-empty rectangle returns false */
+/** gfx_rect_is_empty for straight non-empty rectangle returns false */
 PCUT_TEST(rect_is_empty_neg)
 {
@@ -662,4 +680,99 @@
 }
 
+/** gfx_rect_is_incident for neighboring rectangles returns false */
+PCUT_TEST(rect_is_incident_neighbor)
+{
+	gfx_rect_t a;
+	gfx_rect_t b;
+
+	a.p0.x = 1;
+	a.p0.y = 2;
+	a.p1.x = 3;
+	a.p1.y = 4;
+
+	b.p0.x = 3;
+	b.p0.y = 2;
+	b.p1.x = 5;
+	b.p1.y = 6;
+
+	PCUT_ASSERT_FALSE(gfx_rect_is_incident(&a, &b));
+}
+
+/** gfx_rect_is_incident for a inside b returns true */
+PCUT_TEST(rect_is_incident_a_inside_b)
+{
+	gfx_rect_t a;
+	gfx_rect_t b;
+
+	a.p0.x = 2;
+	a.p0.y = 3;
+	a.p1.x = 4;
+	a.p1.y = 5;
+
+	b.p0.x = 1;
+	b.p0.y = 2;
+	b.p1.x = 5;
+	b.p1.y = 6;
+
+	PCUT_ASSERT_TRUE(gfx_rect_is_incident(&a, &b));
+}
+
+/** gfx_rect_is_incident for b inside a returns true */
+PCUT_TEST(rect_is_incident_b_inside_a)
+{
+	gfx_rect_t a;
+	gfx_rect_t b;
+
+	a.p0.x = 1;
+	a.p0.y = 2;
+	a.p1.x = 5;
+	a.p1.y = 6;
+
+	b.p0.x = 2;
+	b.p0.y = 3;
+	b.p1.x = 4;
+	b.p1.y = 5;
+
+	PCUT_ASSERT_TRUE(gfx_rect_is_incident(&a, &b));
+}
+
+/** gfx_rect_is_incident for a and b sharing corner returns true */
+PCUT_TEST(rect_is_incident_corner)
+{
+	gfx_rect_t a;
+	gfx_rect_t b;
+
+	a.p0.x = 1;
+	a.p0.y = 2;
+	a.p1.x = 3;
+	a.p1.y = 4;
+
+	b.p0.x = 2;
+	b.p0.y = 3;
+	b.p1.x = 4;
+	b.p1.y = 5;
+
+	PCUT_ASSERT_TRUE(gfx_rect_is_incident(&a, &b));
+}
+
+/** gfx_rect_is_incident for a == b returns true */
+PCUT_TEST(rect_is_incident_same)
+{
+	gfx_rect_t a;
+	gfx_rect_t b;
+
+	a.p0.x = 1;
+	a.p0.y = 2;
+	a.p1.x = 3;
+	a.p1.y = 4;
+
+	b.p0.x = 1;
+	b.p0.y = 2;
+	b.p1.x = 3;
+	b.p1.y = 4;
+
+	PCUT_ASSERT_TRUE(gfx_rect_is_incident(&a, &b));
+}
+
 /** gfx_pix_inside_rect for  */
 PCUT_TEST(pix_inside_rect)
Index: uspace/srv/hid/display/display.c
===================================================================
--- uspace/srv/hid/display/display.c	(revision d70e7b7bcaa004700e0af401f3e5b48e47f018c1)
+++ uspace/srv/hid/display/display.c	(revision 6301a24fb081993e0e1d27b0a61a9bab72fca055)
@@ -570,4 +570,15 @@
 	}
 
+	/* Paint window previews for windows being resized or moved */
+	wnd = ds_display_last_window(disp);
+	while (wnd != NULL) {
+		rc = ds_window_paint_preview(wnd, rect);
+		if (rc != EOK)
+			return rc;
+
+		wnd = ds_display_prev_window(wnd);
+	}
+
+	/* Paint pointers */
 	seat = ds_display_first_seat(disp);
 	while (seat != NULL) {
Index: uspace/srv/hid/display/seat.c
===================================================================
--- uspace/srv/hid/display/seat.c	(revision d70e7b7bcaa004700e0af401f3e5b48e47f018c1)
+++ uspace/srv/hid/display/seat.c	(revision 6301a24fb081993e0e1d27b0a61a9bab72fca055)
@@ -251,5 +251,4 @@
 {
 	gfx_rect_t new_rect;
-	gfx_rect_t isect;
 	gfx_rect_t envelope;
 	errno_t rc;
@@ -257,6 +256,5 @@
 	ds_seat_get_pointer_rect(seat, &new_rect);
 
-	gfx_rect_clip(old_rect, &new_rect, &isect);
-	if (gfx_rect_is_empty(&isect)) {
+	if (gfx_rect_is_incident(old_rect, &new_rect)) {
 		/* Rectangles do not intersect. Repaint them separately. */
 		rc = ds_display_paint(seat->display, &new_rect);
Index: uspace/srv/hid/display/window.c
===================================================================
--- uspace/srv/hid/display/window.c	(revision d70e7b7bcaa004700e0af401f3e5b48e47f018c1)
+++ uspace/srv/hid/display/window.c	(revision 6301a24fb081993e0e1d27b0a61a9bab72fca055)
@@ -50,4 +50,5 @@
 
 static void ds_window_update_cb(void *, gfx_rect_t *);
+static void ds_window_get_preview_rect(ds_window_t *, gfx_rect_t *);
 
 /** Create window.
@@ -205,31 +206,66 @@
 }
 
-/** Start moving a window by mouse drag.
- *
- * @param wnd Window
- * @param pos Position where mouse button was pressed
- */
-static void ds_window_start_move(ds_window_t *wnd, gfx_coord2_t *pos)
-{
+/** Get the preview rectangle for a window.
+ *
+ * Get the preview rectangle if the window is being resized or moved.
+ * If the window is not being resized or moved, return an empty rectangle.
+ *
+ * @param wnd Window
+ * @param rect Place to store preview rectangle
+ */
+static void ds_window_get_preview_rect(ds_window_t *wnd, gfx_rect_t *rect)
+{
+	switch (wnd->state) {
+	case dsw_idle:
+		break;
+	case dsw_moving:
+		gfx_rect_translate(&wnd->preview_pos, &wnd->rect, rect);
+		return;
+	case dsw_resizing:
+		gfx_rect_translate(&wnd->dpos, &wnd->preview_rect, rect);
+		return;
+	}
+
+	rect->p0.x = 0;
+	rect->p0.y = 0;
+	rect->p1.x = 0;
+	rect->p1.y = 0;
+}
+
+/** Paint window preview if the window is being moved or resized.
+ *
+ * If the window is not being resized or moved, take no action and return
+ * success.
+ *
+ * @param wnd Window for which to paint preview
+ * @param rect Clipping rectangle
+ * @return EOK on success or an error code
+ */
+errno_t ds_window_paint_preview(ds_window_t *wnd, gfx_rect_t *rect)
+{
+	errno_t rc;
 	gfx_color_t *color;
+	gfx_rect_t prect;
+	gfx_rect_t drect;
 	gfx_context_t *gc;
-	gfx_rect_t drect;
-	errno_t rc;
-
-	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_start_move (%d, %d)",
-	    (int) pos->x, (int) pos->y);
-
-	if (wnd->state != dsw_idle)
-		return;
-
-	wnd->orig_pos = *pos;
-	wnd->state = dsw_moving;
-	wnd->preview_pos = wnd->dpos;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_paint_preview");
+
+	/*
+	 * Get preview rectangle. If the window is not being resized/moved,
+	 * we should get an empty rectangle.
+	 */
+	ds_window_get_preview_rect(wnd, &prect);
+	if (gfx_rect_is_empty(&prect)) {
+		/* There is nothing to paint */
+		return EOK;
+	}
+
+	/* Clip rendering to the clipping rectangle */
+	gfx_rect_clip(&prect, rect, &drect);
 
 	rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &color);
 	if (rc != EOK)
-		return;
-
-	gfx_rect_translate(&wnd->dpos, &wnd->rect, &drect);
+		return rc;
 
 	gc = ds_display_get_gc(wnd->display); // XXX
@@ -240,4 +276,85 @@
 
 	gfx_color_delete(color);
+	return EOK;
+}
+
+/** Repaint window preview when resizing or moving.
+ *
+ * Repaint the window preview wich was previously at rectangle @a old_rect.
+ * The current preview rectangle is determined from window state. If
+ * the window did not previously have a preview, @a old_rect should point
+ * to an empty rectangle or be NULL. When window has finished
+ * moving or resizing, the preview will be cleared.
+ *
+ * @param wnd Window for which to paint preview
+ * @param rect Clipping rectangle
+ * @return EOK on success or an error code
+ */
+static errno_t ds_window_repaint_preview(ds_window_t *wnd, gfx_rect_t *old_rect)
+{
+	errno_t rc;
+	gfx_rect_t prect;
+	gfx_rect_t envelope;
+	bool oldr;
+	bool newr;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_repaint_preview");
+
+	/*
+	 * Get current preview rectangle. If the window is not being resized/moved,
+	 * we should get an empty rectangle.
+	 */
+	ds_window_get_preview_rect(wnd, &prect);
+
+	oldr = (old_rect != NULL) && !gfx_rect_is_empty(old_rect);
+	newr = !gfx_rect_is_empty(&prect);
+
+	if (oldr && newr && gfx_rect_is_incident(old_rect, &prect)) {
+		/*
+		 * As an optimization, repaint both rectangles in a single
+		 * operation.
+		 */
+
+		gfx_rect_envelope(old_rect, &prect, &envelope);
+
+		rc = ds_display_paint(wnd->display, &envelope);
+		if (rc != EOK)
+			return rc;
+	} else {
+		/* Repaint each rectangle separately */
+		if (oldr) {
+			rc = ds_display_paint(wnd->display, old_rect);
+			if (rc != EOK)
+				return rc;
+		}
+
+		if (newr) {
+			rc = ds_display_paint(wnd->display, &prect);
+			if (rc != EOK)
+				return rc;
+		}
+	}
+
+	return EOK;
+}
+
+/** Start moving a window by mouse drag.
+ *
+ * @param wnd Window
+ * @param pos Position where mouse button was pressed
+ */
+static void ds_window_start_move(ds_window_t *wnd, gfx_coord2_t *pos)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_start_move (%d, %d)",
+	    (int) pos->x, (int) pos->y);
+
+	if (wnd->state != dsw_idle)
+		return;
+
+	wnd->orig_pos = *pos;
+	wnd->state = dsw_moving;
+	wnd->preview_pos = wnd->dpos;
+
+	(void) ds_window_repaint_preview(wnd, NULL);
 }
 
@@ -251,4 +368,5 @@
 	gfx_coord2_t dmove;
 	gfx_coord2_t nwpos;
+	gfx_rect_t old_rect;
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_finish_move (%d, %d)",
@@ -258,6 +376,8 @@
 
 	gfx_coord2_subtract(pos, &wnd->orig_pos, &dmove);
-
 	gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
+
+	ds_window_get_preview_rect(wnd, &old_rect);
+
 	wnd->dpos = nwpos;
 	wnd->state = dsw_idle;
@@ -275,8 +395,5 @@
 	gfx_coord2_t dmove;
 	gfx_coord2_t nwpos;
-	gfx_rect_t drect;
-	gfx_color_t *color;
-	gfx_context_t *gc;
-	errno_t rc;
+	gfx_rect_t old_rect;
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_move (%d, %d)",
@@ -285,25 +402,11 @@
 	assert(wnd->state == dsw_moving);
 
-	gfx_rect_translate(&wnd->preview_pos, &wnd->rect, &drect);
-	ds_display_paint(wnd->display, &drect);
-
 	gfx_coord2_subtract(pos, &wnd->orig_pos, &dmove);
-
 	gfx_coord2_add(&wnd->dpos, &dmove, &nwpos);
+
+	ds_window_get_preview_rect(wnd, &old_rect);
 	wnd->preview_pos = nwpos;
 
-	gfx_rect_translate(&nwpos, &wnd->rect, &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);
+	(void) ds_window_repaint_preview(wnd, &old_rect);
 }
 
@@ -335,4 +438,6 @@
 	ctype = display_cursor_from_wrsz(rsztype);
 	ds_seat_set_wm_cursor(seat, wnd->display->cursor[ctype]);
+
+	(void) ds_window_repaint_preview(wnd, NULL);
 }
 
@@ -352,7 +457,4 @@
 
 	assert(wnd->state == dsw_resizing);
-
-	(void) ds_display_paint(wnd->display, NULL);
-
 	gfx_coord2_subtract(pos, &wnd->orig_pos, &dresize);
 
@@ -366,4 +468,6 @@
 	seat = ds_display_first_seat(wnd->display);
 	ds_seat_set_wm_cursor(seat, NULL);
+
+	(void) ds_display_paint(wnd->display, NULL);
 }
 
@@ -377,8 +481,5 @@
 	gfx_coord2_t dresize;
 	gfx_rect_t nrect;
-	gfx_rect_t drect;
-	gfx_color_t *color;
-	gfx_context_t *gc;
-	errno_t rc;
+	gfx_rect_t old_rect;
 
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "ds_window_update_resize (%d, %d)",
@@ -387,24 +488,10 @@
 	assert(wnd->state == dsw_resizing);
 
-	gfx_rect_translate(&wnd->dpos, &wnd->preview_rect, &drect);
-	(void) ds_display_paint(wnd->display, &drect);
-
 	gfx_coord2_subtract(pos, &wnd->orig_pos, &dresize);
-
 	ds_window_calc_resize(wnd, &dresize, &nrect);
-	gfx_rect_translate(&wnd->dpos, &nrect, &drect);
+
+	ds_window_get_preview_rect(wnd, &old_rect);
 	wnd->preview_rect = nrect;
-
-	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);
+	(void) ds_window_repaint_preview(wnd, &old_rect);
 }
 
Index: uspace/srv/hid/display/window.h
===================================================================
--- uspace/srv/hid/display/window.h	(revision d70e7b7bcaa004700e0af401f3e5b48e47f018c1)
+++ uspace/srv/hid/display/window.h	(revision 6301a24fb081993e0e1d27b0a61a9bab72fca055)
@@ -56,4 +56,5 @@
 extern gfx_context_t *ds_window_get_ctx(ds_window_t *);
 extern errno_t ds_window_paint(ds_window_t *, gfx_rect_t *);
+errno_t ds_window_paint_preview(ds_window_t *, gfx_rect_t *);
 extern errno_t ds_window_post_kbd_event(ds_window_t *, kbd_event_t *);
 extern errno_t ds_window_post_pos_event(ds_window_t *, pos_event_t *);
