Index: uspace/srv/hid/display/test/window.c
===================================================================
--- uspace/srv/hid/display/test/window.c	(revision 3be53668a72d42907f6124a3b95374fde7f15a53)
+++ uspace/srv/hid/display/test/window.c	(revision 6828a56f6f3bca46ff6f9dee859fbd15fd17292e)
@@ -36,4 +36,5 @@
 #include "../client.h"
 #include "../display.h"
+#include "../idevcfg.h"
 #include "../seat.h"
 #include "../window.h"
@@ -1273,4 +1274,66 @@
 }
 
+/** ds_window_orig_seat() correctly compares seats */
+PCUT_TEST(window_orig_seat)
+{
+	gfx_context_t *gc;
+	ds_display_t *disp;
+	ds_client_t *client;
+	ds_seat_t *seat0;
+	ds_seat_t *seat1;
+	sysarg_t devid0;
+	sysarg_t devid1;
+	ds_idevcfg_t *cfg0;
+	ds_idevcfg_t *cfg1;
+	ds_window_t *wnd;
+	display_wnd_params_t params;
+	errno_t rc;
+
+	rc = gfx_context_new(&dummy_ops, NULL, &gc);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_display_create(gc, df_none, &disp);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_client_create(disp, NULL, NULL, &client);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, "Alice", &seat0);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_seat_create(disp, "Bob", &seat1);
+	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);
+
+	devid0 = 42;
+	devid1 = 43;
+
+	rc = ds_idevcfg_create(disp, devid0, seat0, &cfg0);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = ds_idevcfg_create(disp, devid1, seat1, &cfg1);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	wnd->state = dsw_moving;
+	wnd->orig_pos_id = devid0;
+
+	PCUT_ASSERT_TRUE(ds_window_orig_seat(wnd, devid0));
+	PCUT_ASSERT_FALSE(ds_window_orig_seat(wnd, devid1));
+
+	ds_idevcfg_destroy(cfg0);
+	ds_idevcfg_destroy(cfg1);
+	ds_window_destroy(wnd);
+	ds_seat_destroy(seat0);
+	ds_seat_destroy(seat1);
+	ds_client_destroy(client);
+	ds_display_destroy(disp);
+}
+
 static errno_t dummy_set_color(void *arg, gfx_color_t *color)
 {
Index: uspace/srv/hid/display/window.c
===================================================================
--- uspace/srv/hid/display/window.c	(revision 3be53668a72d42907f6124a3b95374fde7f15a53)
+++ uspace/srv/hid/display/window.c	(revision 6828a56f6f3bca46ff6f9dee859fbd15fd17292e)
@@ -656,10 +656,13 @@
 
 	if (event->type == POS_RELEASE) {
-		if (wnd->state == dsw_moving) {
+		/* Finish move/resize if they were started by the same seat */
+		if (wnd->state == dsw_moving &&
+		    ds_window_orig_seat(wnd, pos_id)) {
 			ds_window_finish_move(wnd, &pos);
 			return EOK;
 		}
 
-		if (wnd->state == dsw_resizing) {
+		if (wnd->state == dsw_resizing &&
+		    ds_window_orig_seat(wnd, pos_id)) {
 			ds_window_finish_resize(wnd, &pos);
 			return EOK;
@@ -668,10 +671,13 @@
 
 	if (event->type == POS_UPDATE) {
-		if (wnd->state == dsw_moving) {
+		/* Update move/resize if they were started by the same seat */
+		if (wnd->state == dsw_moving &&
+		    ds_window_orig_seat(wnd, pos_id)) {
 			ds_window_update_move(wnd, &pos);
 			return EOK;
 		}
 
-		if (wnd->state == dsw_resizing) {
+		if (wnd->state == dsw_resizing &&
+		    ds_window_orig_seat(wnd, pos_id)) {
 			ds_window_update_resize(wnd, &pos);
 			return EOK;
@@ -1125,4 +1131,33 @@
 }
 
+/** Determine if input device belongs to the same seat as the original device.
+ *
+ * Compare the seat ownning @a idev_id with the seat owning @a wnd->orig_pos_id
+ * (the device that started the window move or resize).
+ *
+ * This is used to make sure that, when two seats focus the same window,
+ * only devices owned by the seat that started the resize or move can
+ * affect it. Otherwise moving the other pointer(s) would disrupt the
+ * resize or move operation.
+ *
+ * @param wnd Window (that is currently being resized or moved)
+ * @param idev_id Input device ID
+ * @return @c true iff idev_id is owned by the same seat as the input
+ *         device that started the resize or move
+ */
+bool ds_window_orig_seat(ds_window_t *wnd, sysarg_t idev_id)
+{
+	ds_seat_t *orig_seat;
+	ds_seat_t *seat;
+
+	/* Window must be in state such that wnd->orig_pos_id is valid */
+	assert(wnd->state == dsw_moving || wnd->state == dsw_resizing);
+
+	orig_seat = ds_display_seat_by_idev(wnd->display, wnd->orig_pos_id);
+	seat = ds_display_seat_by_idev(wnd->display, idev_id);
+
+	return seat == orig_seat;
+}
+
 /** Window memory GC invalidate callback.
  *
Index: uspace/srv/hid/display/window.h
===================================================================
--- uspace/srv/hid/display/window.h	(revision 3be53668a72d42907f6124a3b95374fde7f15a53)
+++ uspace/srv/hid/display/window.h	(revision 6828a56f6f3bca46ff6f9dee859fbd15fd17292e)
@@ -80,4 +80,5 @@
 extern ds_window_t *ds_window_find_alt(ds_window_t *, display_wnd_flags_t);
 extern void ds_window_unfocus(ds_window_t *);
+extern bool ds_window_orig_seat(ds_window_t *, sysarg_t);
 
 #endif
