Index: uspace/lib/vt/include/vt/vt100.h
===================================================================
--- uspace/lib/vt/include/vt/vt100.h	(revision 5f5d3757f78727d04ad0b50a7312cbe9fd6b71a0)
+++ uspace/lib/vt/include/vt/vt100.h	(revision 5e0acaac7937239d70145f39d7dcc45e498b3776)
@@ -37,4 +37,5 @@
 #include <io/charfield.h>
 #include <io/keycode.h>
+#include <io/pos_event.h>
 #include <ipc/common.h>
 #include <uchar.h>
@@ -77,4 +78,5 @@
 	void (*flush)(void *);
 	void (*key)(void *, keymod_t, keycode_t, char);
+	void (*pos_event)(void *, pos_event_t *);
 } vt100_cb_t;
 
@@ -124,6 +126,12 @@
 	vts_1b5b33,
 	/** Prefix 1b 5b 36 */
-	vts_1b5b36
+	vts_1b5b36,
+	/** Prefix 1b 5b 3c - mouse report */
+	vts_1b5b3c
 } vt100_state_t;
+
+enum {
+	INNUM_MAX = 3
+};
 
 /** VT100 instance */
@@ -151,4 +159,8 @@
 	/** Input decoding state */
 	vt100_state_t state;
+	/** Decoded numeric parameters */
+	uint16_t innum[INNUM_MAX];
+	/** Index of current numeric parameter */
+	unsigned inncnt;
 } vt100_t;
 
@@ -170,4 +182,5 @@
 extern void vt100_set_attr(vt100_t *, char_attrs_t);
 extern void vt100_cursor_visibility(vt100_t *, bool);
+extern void vt100_set_button_reporting(vt100_t *, bool);
 extern void vt100_putuchar(vt100_t *, char32_t);
 extern void vt100_flush(vt100_t *);
Index: uspace/lib/vt/src/vt100.c
===================================================================
--- uspace/lib/vt/src/vt100.c	(revision 5f5d3757f78727d04ad0b50a7312cbe9fd6b71a0)
+++ uspace/lib/vt/src/vt100.c	(revision 5e0acaac7937239d70145f39d7dcc45e498b3776)
@@ -32,4 +32,5 @@
  */
 
+#include <ctype.h>
 #include <errno.h>
 #include <io/color.h>
@@ -309,4 +310,24 @@
 }
 
+/** Set mouse button press/release reporting.
+ *
+ * @param vt VT instance
+ * @param @c true to enable button press/release reporting
+ */
+void vt100_set_button_reporting(vt100_t *vt, bool enable)
+{
+	if (enable) {
+		/* Enable button tracking */
+		vt->cb->control_puts(vt->arg, "\033[?1000h");
+		/* Enable SGR encoding of mouse reports */
+		vt->cb->control_puts(vt->arg, "\033[?1006h");
+	} else {
+		/* Disable button tracking */
+		vt->cb->control_puts(vt->arg, "\033[?1000l");
+		/* Disable SGR encoding of mouse reports */
+		vt->cb->control_puts(vt->arg, "\033[?1006l");
+	}
+}
+
 /** Print Unicode character.
  *
@@ -349,4 +370,27 @@
 }
 
+/** Generate position event callback.
+ * *
+ * @param vt VT instance
+ * @param ev Position event
+ */
+static void vt100_pos_event(vt100_t *vt, pos_event_t *ev)
+{
+	vt->cb->pos_event(vt->arg, ev);
+}
+
+/** Clear number decoder state.
+ *
+ * @param vt VT instance
+ */
+static void vt100_clear_innum(vt100_t *vt)
+{
+	unsigned i;
+
+	vt->inncnt = 0;
+	for (i = 0; i < INNUM_MAX; i++)
+		vt->innum[i] = 0;
+}
+
 /** Process input character with prefix 1b.
  *
@@ -576,4 +620,7 @@
 		vt->state = vts_1b5b36;
 		break;
+	case 0x3c:
+		vt->state = vts_1b5b3c;
+		break;
 	case 0x41:
 		vt100_key(vt, 0, KC_UP, 0);
@@ -966,4 +1013,59 @@
 		vt->state = vts_base;
 		break;
+	}
+}
+
+/** Process input character with prefix 1b 5b 3c - mouse report.
+ *
+ * @param vt VT instance
+ * @param c Input character
+ */
+static void vt100_rcvd_1b5b3c(vt100_t *vt, char c)
+{
+	pos_event_t ev;
+
+	if (isdigit(c)) {
+		/* Decode next base-10 digit */
+		vt->innum[vt->inncnt] = vt->innum[vt->inncnt] * 10 + (c - '0');
+	} else if (c == ';') {
+		/* Move to next parameter */
+		if (vt->inncnt >= INNUM_MAX - 1) {
+			vt->state = vts_base;
+			vt100_clear_innum(vt);
+			return;
+		}
+		++vt->inncnt;
+	} else {
+		switch (c) {
+		case 'M':
+		case 'm':
+			/* Button press / release */
+			ev.pos_id = 0;
+			ev.type = (c == 'M') ? POS_PRESS : POS_RELEASE;
+
+			/*
+			 * VT reports button 0 = left button,
+			 * 1 = middle, 2 = right.
+			 * pos_event needs 1 = left, 2 = right, 3 = middle,...
+			 * so right and middle need to be reversed.
+			 */
+			switch (vt->innum[0]) {
+			case 1:
+				ev.btn_num = 3;
+				break;
+			case 2:
+				ev.btn_num = 2;
+				break;
+			default:
+				ev.btn_num = 1 + vt->innum[0];
+				break;
+			}
+			ev.hpos = vt->innum[1] - 1;
+			ev.vpos = vt->innum[2] - 1;
+			vt100_pos_event(vt, &ev);
+			break;
+		}
+		vt100_clear_innum(vt);
+		vt->state = vts_base;
 	}
 }
@@ -1453,4 +1555,7 @@
 		vt100_rcvd_1b5b36(vt, c);
 		break;
+	case vts_1b5b3c:
+		vt100_rcvd_1b5b3c(vt, c);
+		break;
 	}
 }
Index: uspace/srv/hid/remcons/remcons.c
===================================================================
--- uspace/srv/hid/remcons/remcons.c	(revision 5f5d3757f78727d04ad0b50a7312cbe9fd6b71a0)
+++ uspace/srv/hid/remcons/remcons.c	(revision 5e0acaac7937239d70145f39d7dcc45e498b3776)
@@ -126,4 +126,5 @@
 static void remcons_vt_flush(void *);
 static void remcons_vt_key(void *, keymod_t, keycode_t, char);
+static void remcons_vt_pos_event(void *, pos_event_t *);
 
 static vt100_cb_t remcons_vt_cb = {
@@ -131,5 +132,6 @@
 	.control_puts = remcons_vt_cputs,
 	.flush = remcons_vt_flush,
-	.key = remcons_vt_key
+	.key = remcons_vt_key,
+	.pos_event = remcons_vt_pos_event
 };
 
@@ -369,4 +371,24 @@
 	event->cev.ev.key.key = key;
 	event->cev.ev.key.c = c;
+
+	return event;
+}
+
+/** Creates new position event.
+ *
+ * @param ev Position event.
+ * @param c Pressed character.
+ */
+static remcons_event_t *new_pos_event(pos_event_t *ev)
+{
+	remcons_event_t *event = malloc(sizeof(remcons_event_t));
+	if (event == NULL) {
+		fprintf(stderr, "Out of memory.\n");
+		return NULL;
+	}
+
+	link_initialize(&event->link);
+	event->cev.type = CEV_POS;
+	event->cev.ev.pos = *ev;
 
 	return event;
@@ -627,4 +649,15 @@
 }
 
+static void remcons_vt_pos_event(void *arg, pos_event_t *ev)
+{
+	remcons_t *remcons = (remcons_t *)arg;
+
+	remcons_event_t *cev = new_pos_event(ev);
+	if (cev == NULL)
+		return;
+
+	list_append(&cev->link, &remcons->in_events);
+}
+
 /** Window size update callback.
  *
@@ -700,4 +733,5 @@
 		vt100_cls(remcons->vt);
 		vt100_set_pos(remcons->vt, 0, 0);
+		vt100_set_button_reporting(remcons->vt, true);
 	}
 
