Index: uspace/lib/display/include/types/display/cursor.h
===================================================================
--- uspace/lib/display/include/types/display/cursor.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
+++ uspace/lib/display/include/types/display/cursor.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2020 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdisplay
+ * @{
+ */
+/** @file
+ */
+
+#ifndef _LIBDISPLAY_TYPES_DISPLAY_CURSOR_H_
+#define _LIBDISPLAY_TYPES_DISPLAY_CURSOR_H_
+
+/** Stock cursor types */
+typedef enum {
+	/** Standard arrow */
+	dcurs_arrow,
+	/** Double arrow pointing up and down */
+	dcurs_size_ud,
+	/** Double arrow pointing left and right */
+	dcurs_size_lr,
+	/** Double arrow pointing up-left and down-right */
+	dcurs_size_uldr,
+	/** Double arrow pointing up-right nad down-left */
+	dcurs_size_urdl
+} display_stock_cursor_t;
+
+enum {
+	/** Number of stock cursor types */
+	dcurs_limit = dcurs_size_urdl
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/display/cursimg.c
===================================================================
--- uspace/srv/hid/display/cursimg.c	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
+++ uspace/srv/hid/display/cursimg.c	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup display
+ * @{
+ */
+/**
+ * @file Display server built-in cursor images
+ */
+
+#include <types/display/cursor.h>
+#include "cursimg.h"
+
+static uint8_t arrow_img[] = {
+	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0,
+	1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0,
+	1, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
+	1, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
+	1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0,
+	1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0,
+	1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0,
+	1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
+	1, 2, 2, 2, 1, 2, 2, 1, 0, 0, 0, 0, 0,
+	1, 2, 2, 1, 0, 1, 2, 2, 1, 0, 0, 0, 0,
+	1, 2, 1, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0,
+	1, 1, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0,
+	1, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0
+};
+
+ds_cursimg_t ds_cursimg[dcurs_limit] = {
+	{
+		.rect = { 0, 0, 13, 21 },
+		.image = arrow_img
+	}
+};
+
+/** @}
+ */
Index: uspace/srv/hid/display/cursimg.h
===================================================================
--- uspace/srv/hid/display/cursimg.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
+++ uspace/srv/hid/display/cursimg.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2020 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup display
+ * @{
+ */
+/**
+ * @file Display server built-in cursor images
+ */
+
+#ifndef CURSIMG_H
+#define CURSIMG_H
+
+#include "types/display/cursimg.h"
+
+extern ds_cursimg_t ds_cursimg[dcurs_limit];
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/display/cursor.c
===================================================================
--- uspace/srv/hid/display/cursor.c	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
+++ uspace/srv/hid/display/cursor.c	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2020 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup display
+ * @{
+ */
+/**
+ * @file Display server cursor
+ */
+
+#include <gfx/bitmap.h>
+#include <gfx/coord.h>
+#include <stdlib.h>
+#include "cursor.h"
+#include "display.h"
+
+/** Create cursor.
+ *
+ * @param disp Display
+ * @param rect Rectangle bounding cursor graphic
+ * @param image Cursor image (one entire byte per pixel)
+ * @param rcursor Place to store pointer to new cursor.
+ *
+ * @return EOK on success or an error code
+ */
+errno_t ds_cursor_create(ds_display_t *disp, gfx_rect_t *rect,
+    const uint8_t *image, ds_cursor_t **rcursor)
+{
+	ds_cursor_t *cursor = NULL;
+	errno_t rc;
+
+	cursor = calloc(1, sizeof(ds_cursor_t));
+	if (cursor == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	ds_display_add_cursor(disp, cursor);
+
+	cursor->rect = *rect;
+	cursor->image = image;
+	*rcursor = cursor;
+	return EOK;
+error:
+	return rc;
+}
+
+/** Destroy cusror.
+ *
+ * @param cursor Cursor
+ */
+void ds_cursor_destroy(ds_cursor_t *cursor)
+{
+	list_remove(&cursor->ldisplay);
+
+	if (cursor->bitmap != NULL)
+		gfx_bitmap_destroy(cursor->bitmap);
+
+	free(cursor);
+}
+
+/** Paint cusor.
+ *
+ * @param cursor Cusor to paint
+ * @param pos Position to paint at
+ * @return EOK on success or an error code
+ */
+errno_t ds_cursor_paint(ds_cursor_t *cursor, gfx_coord2_t *pos)
+{
+	gfx_context_t *dgc;
+	gfx_coord_t x, y;
+	gfx_bitmap_params_t bparams;
+	gfx_bitmap_alloc_t alloc;
+	gfx_coord2_t dims;
+	pixelmap_t pixelmap;
+	pixel_t pixel;
+	const uint8_t *pp;
+	errno_t rc;
+
+	dgc = ds_display_get_gc(cursor->display); // XXX
+
+	gfx_bitmap_params_init(&bparams);
+	bparams.rect = cursor->rect;
+
+	if (cursor->bitmap == NULL) {
+		rc = gfx_bitmap_create(dgc, &bparams, NULL, &cursor->bitmap);
+		if (rc != EOK)
+			goto error;
+
+		rc = gfx_bitmap_get_alloc(cursor->bitmap, &alloc);
+		if (rc != EOK) {
+			gfx_bitmap_destroy(cursor->bitmap);
+			cursor->bitmap = NULL;
+			goto error;
+		}
+
+		gfx_rect_dims(&cursor->rect, &dims);
+		pixelmap.width = dims.x;
+		pixelmap.height = dims.y;
+		pixelmap.data = alloc.pixels;
+
+		pp = cursor->image;
+		for (y = 0; y < dims.y; y++) {
+			for (x = 0; x < dims.x; x++) {
+				switch (*pp) {
+				case 1:
+					pixel = PIXEL(0, 0, 0, 0);
+					break;
+				case 2:
+					pixel = PIXEL(0, 255, 255, 255);
+					break;
+				default:
+					pixel = PIXEL(0, 0, 255, 255);
+					break;
+				}
+
+				pixelmap_put_pixel(&pixelmap, x, y, pixel);
+				++pp;
+			}
+		}
+
+		return EOK;
+	}
+
+	return gfx_bitmap_render(cursor->bitmap, NULL, pos);
+error:
+	return rc;
+}
+
+/** Get rectangle covered by cursor when drawn at a specified position.
+ *
+ * @param cursor Cursor
+ * @param pos Position where cursor is situated
+ * @param rect Place to store rectangle covered by cursor
+ */
+void ds_cursor_get_rect(ds_cursor_t *cursor, gfx_coord2_t *pos,
+    gfx_rect_t *drect)
+{
+	gfx_rect_translate(pos, &cursor->rect, drect);
+}
+
+/** @}
+ */
Index: uspace/srv/hid/display/cursor.h
===================================================================
--- uspace/srv/hid/display/cursor.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
+++ uspace/srv/hid/display/cursor.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup display
+ * @{
+ */
+/**
+ * @file Display server cursor
+ */
+
+#ifndef CURSOR_H
+#define CURSOR_H
+
+#include <errno.h>
+#include <types/gfx/coord.h>
+#include <stdint.h>
+#include "types/display/display.h"
+#include "types/display/cursor.h"
+
+extern errno_t ds_cursor_create(ds_display_t *, gfx_rect_t *, const uint8_t *,
+    ds_cursor_t **);
+extern void ds_cursor_destroy(ds_cursor_t *);
+extern errno_t ds_cursor_paint(ds_cursor_t *, gfx_coord2_t *);
+extern void ds_cursor_get_rect(ds_cursor_t *, gfx_coord2_t *, gfx_rect_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/display/display.c
===================================================================
--- uspace/srv/hid/display/display.c	(revision 6feccae4e934741d247da783eb3bbef174d9d0ef)
+++ uspace/srv/hid/display/display.c	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -40,4 +40,6 @@
 #include <stdlib.h>
 #include "client.h"
+#include "cursimg.h"
+#include "cursor.h"
 #include "seat.h"
 #include "window.h"
@@ -53,4 +55,6 @@
 {
 	ds_display_t *disp;
+	ds_cursor_t *cursor;
+	int i;
 	errno_t rc;
 
@@ -63,4 +67,15 @@
 		free(disp);
 		return ENOMEM;
+	}
+
+	list_initialize(&disp->cursors);
+
+	for (i = 0; i < dcurs_limit; i++) {
+		rc = ds_cursor_create(disp, &ds_cursimg[i].rect,
+		    ds_cursimg[i].image, &cursor);
+		if (rc != EOK)
+			goto error;
+
+		disp->cursor[i] = cursor;
 	}
 
@@ -73,4 +88,7 @@
 	*rdisp = disp;
 	return EOK;
+error:
+	ds_display_destroy(disp);
+	return rc;
 }
 
@@ -83,4 +101,5 @@
 	assert(list_empty(&disp->clients));
 	assert(list_empty(&disp->seats));
+	/* XXX destroy cursors */
 	gfx_color_delete(disp->bg_color);
 	free(disp);
@@ -462,4 +481,28 @@
 }
 
+/** Add cursor to display.
+ *
+ * @param display Display
+ * @param cursor Cursor
+ */
+void ds_display_add_cursor(ds_display_t *display, ds_cursor_t *cursor)
+{
+	assert(cursor->display == NULL);
+	assert(!link_used(&cursor->ldisplay));
+
+	cursor->display = display;
+	list_prepend(&cursor->ldisplay, &display->cursors);
+}
+
+/** Remove cursor from display.
+ *
+ * @param cursor Cursor
+ */
+void ds_display_remove_cursor(ds_cursor_t *cursor)
+{
+	list_remove(&cursor->ldisplay);
+	cursor->display = NULL;
+}
+
 // XXX
 gfx_context_t *ds_display_get_gc(ds_display_t *display)
Index: uspace/srv/hid/display/display.h
===================================================================
--- uspace/srv/hid/display/display.h	(revision 6feccae4e934741d247da783eb3bbef174d9d0ef)
+++ uspace/srv/hid/display/display.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -43,4 +43,5 @@
 #include <io/kbd_event.h>
 #include "types/display/client.h"
+#include "types/display/cursor.h"
 #include "types/display/ddev.h"
 #include "types/display/display.h"
@@ -75,4 +76,6 @@
 extern ds_ddev_t *ds_display_first_ddev(ds_display_t *);
 extern ds_ddev_t *ds_display_next_ddev(ds_ddev_t *);
+extern void ds_display_add_cursor(ds_display_t *, ds_cursor_t *);
+extern void ds_display_remove_cursor(ds_cursor_t *);
 extern gfx_context_t *ds_display_get_gc(ds_display_t *);
 extern errno_t ds_display_paint_bg(ds_display_t *, gfx_rect_t *);
Index: uspace/srv/hid/display/meson.build
===================================================================
--- uspace/srv/hid/display/meson.build	(revision 6feccae4e934741d247da783eb3bbef174d9d0ef)
+++ uspace/srv/hid/display/meson.build	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -31,4 +31,6 @@
 src = files(
 	'client.c',
+	'cursor.c',
+	'cursimg.c',
 	'ddev.c',
 	'display.c',
@@ -43,8 +45,11 @@
 test_src = files(
 	'client.c',
+	'cursimg.c',
+	'cursor.c',
 	'display.c',
 	'seat.c',
 	'window.c',
 	'test/client.c',
+	'test/cursor.c',
 	'test/display.c',
 	'test/main.c',
Index: uspace/srv/hid/display/seat.c
===================================================================
--- uspace/srv/hid/display/seat.c	(revision 6feccae4e934741d247da783eb3bbef174d9d0ef)
+++ uspace/srv/hid/display/seat.c	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -40,4 +40,5 @@
 #include <stdlib.h>
 #include "client.h"
+#include "cursor.h"
 #include "display.h"
 #include "seat.h"
@@ -61,4 +62,6 @@
 	seat->pntpos.x = 0;
 	seat->pntpos.y = 0;
+
+	seat->cursor = display->cursor[dcurs_arrow];
 
 	*rseat = seat;
@@ -142,53 +145,4 @@
 }
 
-/** Draw cross at seat pointer position.
- *
- * @param seat Seat
- * @param len Cross length
- * @param w Cross extra width
- * @param color Color
- *
- * @return EOK on success or an error code
- */
-static errno_t ds_seat_draw_cross(ds_seat_t *seat, gfx_coord_t len,
-    gfx_coord_t w, gfx_color_t *color)
-{
-	gfx_context_t *gc;
-	gfx_rect_t rect, r0;
-	errno_t rc;
-
-	gc = ds_display_get_gc(seat->display);
-	if (gc == NULL)
-		return EOK;
-
-	rc = gfx_set_color(gc, color);
-	if (rc != EOK)
-		goto error;
-
-	r0.p0.x = -len;
-	r0.p0.y = -w;
-	r0.p1.x = +len + 1;
-	r0.p1.y = +w + 1;
-	gfx_rect_translate(&seat->pntpos, &r0, &rect);
-
-	rc = gfx_fill_rect(gc, &rect);
-	if (rc != EOK)
-		goto error;
-
-	r0.p0.x = -w;
-	r0.p0.y = -len;
-	r0.p1.x = +w + 1;
-	r0.p1.y = +len + 1;
-	gfx_rect_translate(&seat->pntpos, &r0, &rect);
-
-	rc = gfx_fill_rect(gc, &rect);
-	if (rc != EOK)
-		goto error;
-
-	return EOK;
-error:
-	return rc;
-}
-
 /** Draw seat pointer
  *
@@ -199,34 +153,5 @@
 static errno_t ds_seat_draw_pointer(ds_seat_t *seat)
 {
-	errno_t rc;
-	gfx_color_t *black = NULL;
-	gfx_color_t *white;
-
-	rc = gfx_color_new_rgb_i16(0, 0, 0, &black);
-	if (rc != EOK)
-		goto error;
-
-	rc = gfx_color_new_rgb_i16(0xffff, 0xffff, 0xffff, &white);
-	if (rc != EOK)
-		goto error;
-
-	rc = ds_seat_draw_cross(seat, 8, 1, black);
-	if (rc != EOK)
-		goto error;
-
-	rc = ds_seat_draw_cross(seat, 8, 0, white);
-	if (rc != EOK)
-		goto error;
-
-	gfx_color_delete(black);
-	gfx_color_delete(white);
-
-	return EOK;
-error:
-	if (black != NULL)
-		gfx_color_delete(black);
-	if (white != NULL)
-		gfx_color_delete(white);
-	return rc;
+	return ds_cursor_paint(seat->cursor, &seat->pntpos);
 }
 
@@ -241,9 +166,8 @@
 	gfx_rect_t rect;
 
-	rect.p0.x = seat->pntpos.x - 8;
-	rect.p0.y = seat->pntpos.y - 8;
-	rect.p1.x = seat->pntpos.x + 8 + 1;
-	rect.p1.y = seat->pntpos.y + 8 + 1;
-
+	/* Get rectangle covered by cursor */
+	ds_cursor_get_rect(seat->cursor, &seat->pntpos, &rect);
+
+	/* Repaint it */
 	return ds_display_paint(seat->display, &rect);
 }
Index: uspace/srv/hid/display/test/cursor.c
===================================================================
--- uspace/srv/hid/display/test/cursor.c	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
+++ uspace/srv/hid/display/test/cursor.c	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2020 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <pcut/pcut.h>
+
+#include "../cursor.h"
+#include "../cursimg.h"
+#include "../display.h"
+
+PCUT_INIT;
+
+PCUT_TEST_SUITE(cursor);
+
+/** Test ds_cursor_create(), ds_cursor_destroy(). */
+PCUT_TEST(cursor_create_destroy)
+{
+	ds_display_t *disp;
+	ds_cursor_t *cursor;
+	errno_t rc;
+
+	rc = ds_display_create(NULL, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_cursor_create(disp, &ds_cursimg[dcurs_arrow].rect,
+	    ds_cursimg[dcurs_arrow].image, &cursor);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	ds_cursor_destroy(cursor);
+	ds_display_destroy(disp);
+}
+
+/** Test ds_cursor_paint(). */
+PCUT_TEST(cursor_paint)
+{
+	ds_display_t *disp;
+	ds_cursor_t *cursor;
+	errno_t rc;
+
+	rc = ds_display_create(NULL, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_cursor_create(disp, &ds_cursimg[dcurs_arrow].rect,
+	    ds_cursimg[dcurs_arrow].image, &cursor);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	ds_cursor_destroy(cursor);
+	ds_display_destroy(disp);
+}
+
+/** Test ds_cursor_get_rect() */
+PCUT_TEST(cursor_get_rect)
+{
+	ds_display_t *disp;
+	ds_cursor_t *cursor;
+	errno_t rc;
+
+	rc = ds_display_create(NULL, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_cursor_create(disp, &ds_cursimg[dcurs_arrow].rect,
+	    ds_cursimg[dcurs_arrow].image, &cursor);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	ds_cursor_destroy(cursor);
+	ds_display_destroy(disp);
+}
+
+PCUT_EXPORT(cursor);
Index: uspace/srv/hid/display/types/display/cursimg.h
===================================================================
--- uspace/srv/hid/display/types/display/cursimg.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
+++ uspace/srv/hid/display/types/display/cursimg.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2020 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup display
+ * @{
+ */
+/**
+ * @file Display server cursor image type
+ */
+
+#ifndef TYPES_DISPLAY_CURSIMG_H
+#define TYPES_DISPLAY_CURSIMG_H
+
+#include <gfx/coord.h>
+#include <stdint.h>
+
+/** Bitmap in display server window GC */
+typedef struct {
+	gfx_rect_t rect;
+	/** Image, 0 = background, 1 = black, 2 = white */
+	const uint8_t *image;
+} ds_cursimg_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/display/types/display/cursor.h
===================================================================
--- uspace/srv/hid/display/types/display/cursor.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
+++ uspace/srv/hid/display/types/display/cursor.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2020 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup display
+ * @{
+ */
+/**
+ * @file Display server cursor type
+ */
+
+#ifndef TYPES_DISPLAY_CURSOR_H
+#define TYPES_DISPLAY_CURSOR_H
+
+#include <adt/list.h>
+#include <gfx/bitmap.h>
+#include <gfx/coord.h>
+
+/** Bitmap in display server window GC */
+typedef struct ds_cursor {
+	/** Containing display */
+	struct ds_display *display;
+	/** Link to list of all cursors in display */
+	link_t ldisplay;
+	/** Bitmap in the display device */
+	gfx_bitmap_t *bitmap;
+	/** Rectangle represented in the image */
+	gfx_rect_t rect;
+	/** Cursor image */
+	const uint8_t *image;
+} ds_cursor_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/display/types/display/display.h
===================================================================
--- uspace/srv/hid/display/types/display/display.h	(revision 6feccae4e934741d247da783eb3bbef174d9d0ef)
+++ uspace/srv/hid/display/types/display/display.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -42,4 +42,6 @@
 #include <gfx/coord.h>
 #include <io/input.h>
+#include <types/display/cursor.h>
+#include "cursor.h"
 #include "window.h"
 
@@ -74,4 +76,10 @@
 	gfx_color_t *bg_color;
 
+	/** Stock cursors */
+	ds_cursor_t *cursor[dcurs_limit];
+
+	/** List of all cursors */
+	list_t cursors;
+
 	/** Bounding rectangle */
 	gfx_rect_t rect;
Index: uspace/srv/hid/display/types/display/seat.h
===================================================================
--- uspace/srv/hid/display/types/display/seat.h	(revision 6feccae4e934741d247da783eb3bbef174d9d0ef)
+++ uspace/srv/hid/display/types/display/seat.h	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -48,4 +48,6 @@
 	/** Window this seat is focused on */
 	struct ds_window *focus;
+	/** Current seat cursor */
+	struct ds_cursor *cursor;
 	/** Pointer position */
 	gfx_coord2_t pntpos;
Index: uspace/srv/hid/display/window.c
===================================================================
--- uspace/srv/hid/display/window.c	(revision 6feccae4e934741d247da783eb3bbef174d9d0ef)
+++ uspace/srv/hid/display/window.c	(revision 4d8002de0e91d359818180c5e990eb5bf5e63aff)
@@ -31,7 +31,5 @@
  */
 /**
- * @file GFX window backend
- *
- * This implements a graphics context over display server window.
+ * @file Display server window
  */
 
