Index: uspace/srv/hid/compositor/compositor.c
===================================================================
--- uspace/srv/hid/compositor/compositor.c	(revision d17a4a9b9b7d8b1ef841975044255958f61fbacc)
+++ uspace/srv/hid/compositor/compositor.c	(revision 6d5e378b28e2c858f3813b5d4d57fa46f709d753)
@@ -49,6 +49,6 @@
 #include <adt/prodcons.h>
 #include <adt/list.h>
-#include <io/input.h>
 #include <ipc/graph.h>
+#include <ipc/input.h>
 #include <ipc/window.h>
 
@@ -92,8 +92,11 @@
 	sysarg_t id;
 	uint8_t state;
-	desktop_point_t pos;
+	sysarg_t hpos;
+	sysarg_t vpos;
 	sysarg_t btn_num;
-	desktop_point_t btn_pos;
-	desktop_vector_t accum;
+	sysarg_t btn_hpos;
+	sysarg_t btn_vpos;
+	int accum_dx;
+	int accum_dy;
 	sysarg_t grab_flags;
 	bool pressed;
@@ -132,5 +135,6 @@
 	vslmode_t mode;
 	async_sess_t *sess;
-	desktop_point_t pos;
+	sysarg_t hpos;
+	sysarg_t vpos;
 	surface_t *surface;
 } viewport_t;
@@ -139,26 +143,5 @@
 static LIST_INITIALIZE(viewport_list);
 
-/** Input server proxy */
-static input_t *input;
-
-static int comp_key_press(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
-static int comp_mouse_move(input_t *, int, int);
-static int comp_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned);
-static int comp_mouse_button(input_t *, int, int);
-
-static input_ev_ops_t input_ev_ops = {
-	.key = comp_key_press,
-	.move = comp_mouse_move,
-	.abs_move = comp_abs_move,
-	.button = comp_mouse_button
-};
-
-static void input_disconnect(void);
-
-
-static pointer_t *input_pointer(input_t *input)
-{
-	return input->user;
-}
+static async_sess_t *input_sess;
 
 static pointer_t *pointer_create()
@@ -170,10 +153,11 @@
 
 	link_initialize(&p->link);
-	p->pos.x = coord_origin;
-	p->pos.y = coord_origin;
+	p->hpos = coord_origin;
+	p->vpos = coord_origin;
 	p->btn_num = 1;
-	p->btn_pos = p->pos;
-	p->accum.x = 0;
-	p->accum.y = 0;
+	p->btn_hpos = p->hpos;
+	p->btn_vpos = p->vpos;
+	p->accum_dx = 0;
+	p->accum_dy = 0;
 	p->grab_flags = GF_EMPTY;
 	p->pressed = false;
@@ -302,5 +286,5 @@
 		bool isec_vp = rectangle_intersect(
 		    x_dmg_glob, y_dmg_glob, w_dmg_glob, h_dmg_glob,
-		    vp->pos.x, vp->pos.y, w_dmg_vp, h_dmg_vp,
+		    vp->hpos, vp->vpos, w_dmg_vp, h_dmg_vp,
 		    &x_dmg_vp, &y_dmg_vp, &w_dmg_vp, &h_dmg_vp);
 
@@ -308,6 +292,6 @@
 
 			/* Paint background color. */
-			for (sysarg_t y = y_dmg_vp - vp->pos.y; y <  y_dmg_vp - vp->pos.y + h_dmg_vp; ++y) {
-				for (sysarg_t x = x_dmg_vp - vp->pos.x; x < x_dmg_vp - vp->pos.x + w_dmg_vp; ++x) {
+			for (sysarg_t y = y_dmg_vp - vp->vpos; y <  y_dmg_vp - vp->vpos + h_dmg_vp; ++y) {
+				for (sysarg_t x = x_dmg_vp - vp->hpos; x < x_dmg_vp - vp->hpos + w_dmg_vp; ++x) {
 					surface_put_pixel(vp->surface, x, y, bg_color);
 				}
@@ -347,8 +331,7 @@
 					 * coordinates. */
 					transform = win->transform;
-					double_point_t pos;
-					pos.x = vp->pos.x;
-					pos.y = vp->pos.y;
-					transform_translate(&transform, -pos.x, -pos.y);
+					double hpos = vp->hpos;
+					double vpos = vp->vpos;
+					transform_translate(&transform, -hpos, -vpos);
 
 					source_set_transform(&source, transform);				
@@ -357,5 +340,5 @@
 
 					drawctx_transfer(&context,
-					    x_dmg_win - vp->pos.x, y_dmg_win - vp->pos.y, w_dmg_win, h_dmg_win);
+					    x_dmg_win - vp->hpos, y_dmg_win - vp->vpos, w_dmg_win, h_dmg_win);
 				}
 			}
@@ -371,5 +354,5 @@
 				bool isec_ptr = rectangle_intersect(
 				    x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp,
-				    ptr->pos.x, ptr->pos.y, w_dmg_ptr, h_dmg_ptr,
+				    ptr->hpos, ptr->vpos, w_dmg_ptr, h_dmg_ptr,
 				    &x_dmg_ptr, &y_dmg_ptr, &w_dmg_ptr, &h_dmg_ptr);
 
@@ -382,8 +365,8 @@
 
 					pixel_t pix = 0;
-					sysarg_t x_vp = x_dmg_ptr - vp->pos.x;
-					sysarg_t y_vp = y_dmg_ptr - vp->pos.y;
-					sysarg_t x_ptr = x_dmg_ptr - ptr->pos.x;
-					sysarg_t y_ptr = y_dmg_ptr - ptr->pos.y;
+					sysarg_t x_vp = x_dmg_ptr - vp->hpos;
+					sysarg_t y_vp = y_dmg_ptr - vp->vpos;
+					sysarg_t x_ptr = x_dmg_ptr - ptr->hpos;
+					sysarg_t y_ptr = y_dmg_ptr - ptr->vpos;
 
 					for (sysarg_t y = 0; y < h_dmg_ptr; ++y) {
@@ -776,5 +759,5 @@
 		fibril_mutex_unlock(&viewport_list_mtx);
 		loc_service_unregister(winreg_id);
-		input_disconnect();
+		async_hangup(input_sess);
 
 		/* Close all clients and their windows. */
@@ -897,6 +880,6 @@
 
 	link_initialize(&vp->link);
-	vp->pos.x = coord_origin;
-	vp->pos.y = coord_origin;
+	vp->hpos = coord_origin;
+	vp->vpos = coord_origin;
 
 	/* Establish output bidirectional connection. */
@@ -998,8 +981,8 @@
 	/* window_list_mtx locked by caller */
 
-	int dx = pointer->accum.x;
-	int dy = pointer->accum.y;
-	pointer->accum.x = 0;
-	pointer->accum.y = 0;
+	int dx = pointer->accum_dx;
+	int dy = pointer->accum_dy;
+	pointer->accum_dx = 0;
+	pointer->accum_dy = 0;
 
 	bool move = (pointer->grab_flags & GF_MOVE_X) || (pointer->grab_flags & GF_MOVE_Y);
@@ -1072,55 +1055,22 @@
 }
 
-static int comp_abs_move(input_t *input, unsigned x , unsigned y,
-    unsigned max_x, unsigned max_y)
-{
-	/* XXX TODO Use absolute coordinates directly */
-	
-	pointer_t *pointer = input_pointer(input);
-	
-	sysarg_t width, height;
-	
-	fibril_mutex_lock(&viewport_list_mtx);
-	if (list_empty(&viewport_list)) {
-		printf("No viewport found\n");
-		fibril_mutex_unlock(&viewport_list_mtx);
-		return EOK; /* XXX */
-	}
-	link_t *link = list_first(&viewport_list);
-	viewport_t *vp = list_get_instance(link, viewport_t, link);
-	surface_get_resolution(vp->surface, &width, &height);
-	desktop_point_t vp_pos = vp->pos;
-	fibril_mutex_unlock(&viewport_list_mtx);
-
-	desktop_point_t pos_in_viewport;
-	pos_in_viewport.x = x * width / max_x;
-	pos_in_viewport.y = y * height / max_y;
-	
-	/* Calculate offset from pointer */
-	fibril_mutex_lock(&pointer_list_mtx);
-	desktop_vector_t delta;
-	delta.x = (vp_pos.x + pos_in_viewport.x) - pointer->pos.x;
-	delta.y = (vp_pos.y + pos_in_viewport.y) - pointer->pos.y;
-	fibril_mutex_unlock(&pointer_list_mtx);
-	
-	return comp_mouse_move(input, delta.x, delta.y);
-}
-
-static int comp_mouse_move(input_t *input, int dx, int dy)
-{
-	pointer_t *pointer = input_pointer(input);
+static void comp_mouse_move(pointer_t *pointer, ipc_callid_t iid, ipc_call_t *icall)
+{
+	int dx = (int) IPC_GET_ARG1(*icall);
+	int dy = (int) IPC_GET_ARG2(*icall);
 
 	/* Update pointer position. */
 	fibril_mutex_lock(&pointer_list_mtx);
-	desktop_point_t old_pos = pointer->pos;
+	sysarg_t old_hpos = pointer->hpos;
+	sysarg_t old_vpos = pointer->vpos;
 	sysarg_t cursor_width;
 	sysarg_t cursor_height;
 	surface_get_resolution(pointer->cursor.states[pointer->state], 
 	     &cursor_width, &cursor_height);
-	pointer->pos.x += dx;
-	pointer->pos.y += dy;
+	pointer->hpos += dx;
+	pointer->vpos += dy;
 	fibril_mutex_unlock(&pointer_list_mtx);
-	comp_damage(old_pos.x, old_pos.y, cursor_width, cursor_height);
-	comp_damage(old_pos.x + dx, old_pos.y + dy, cursor_width, cursor_height);
+	comp_damage(old_hpos, old_vpos, cursor_width, cursor_height);
+	comp_damage(old_hpos + dx, old_vpos + dy, cursor_width, cursor_height);
 
 	fibril_mutex_lock(&window_list_mtx);
@@ -1134,5 +1084,5 @@
 			sysarg_t width, height;
 			surface_get_resolution(top->surface, &width, &height);
-			within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
+			within_client = comp_coord_to_client(pointer->hpos, pointer->vpos,
 			    top->transform, width, height, &point_x, &point_y);
 			fibril_mutex_unlock(&window_list_mtx);
@@ -1153,6 +1103,6 @@
 		} else {
 			/* Pointer is grabbed by top-level window action. */
-			pointer->accum.x += dx;
-			pointer->accum.y += dy;
+			pointer->accum_dx += dx;
+			pointer->accum_dy += dy;
 #if ANIMATE_WINDOW_TRANSFORMS == 1
 			sysarg_t x, y, width, height;
@@ -1168,14 +1118,16 @@
 	}
 
-	return EOK;
-}
-
-static int comp_mouse_button(input_t *input, int bnum, int bpress)
-{
-	pointer_t *pointer = input_pointer(input);
-
-	if (bpress) {
-		pointer->btn_pos = pointer->pos;
-		pointer->btn_num = bnum;
+	async_answer_0(iid, EOK);
+}
+
+static void comp_mouse_button(pointer_t *pointer, ipc_callid_t iid, ipc_call_t *icall)
+{
+	sysarg_t btn_num = IPC_GET_ARG1(*icall);
+	bool pressed = (bool) IPC_GET_ARG2(*icall);
+
+	if (pressed) {
+		pointer->btn_hpos = pointer->hpos;
+		pointer->btn_vpos = pointer->vpos;
+		pointer->btn_num = btn_num;
 		pointer->pressed = true;
 
@@ -1185,9 +1137,10 @@
 		if (!win || !win->surface) {
 			fibril_mutex_unlock(&window_list_mtx);
-			return EOK;
+			async_answer_0(iid, EOK);
+			return;
 		}
 		sysarg_t x, y, width, height;
 		surface_get_resolution(win->surface, &width, &height);
-		bool within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
+		bool within_client = comp_coord_to_client(pointer->hpos, pointer->vpos,
 		    win->transform, width, height, &x, &y);
 		fibril_mutex_unlock(&window_list_mtx);
@@ -1201,13 +1154,14 @@
 				event->data.pos.pos_id = pointer->id;
 				event->data.pos.type = POS_PRESS;
-				event->data.pos.btn_num = bnum;
+				event->data.pos.btn_num = btn_num;
 				event->data.pos.hpos = x;
 				event->data.pos.vpos = y;
 				comp_post_event(event);
 			} else {
-				return ENOMEM;
-			}
-		}
-	} else if (pointer->pressed && pointer->btn_num == (unsigned)bnum) {
+				async_answer_0(iid, ENOMEM);
+				return;
+			}
+		}
+	} else if (pointer->pressed && pointer->btn_num == btn_num) {
 		pointer->pressed = false;
 
@@ -1224,5 +1178,5 @@
 			if (win->surface) {
 				surface_get_resolution(win->surface, &width, &height);
-				within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
+				within_client = comp_coord_to_client(pointer->hpos, pointer->vpos,
 				    win->transform, width, height, &point_x, &point_y);
 			}
@@ -1237,5 +1191,6 @@
 			pointer->grab_flags = GF_EMPTY;
 			fibril_mutex_unlock(&window_list_mtx);
-			return EOK;
+			async_answer_0(iid, EOK);
+			return;
 		}
 
@@ -1302,5 +1257,5 @@
 				event->data.pos.pos_id = pointer->id;
 				event->data.pos.type = POS_RELEASE;
-				event->data.pos.btn_num = bnum;
+				event->data.pos.btn_num = btn_num;
 				event->data.pos.hpos = point_x;
 				event->data.pos.vpos = point_y;
@@ -1308,5 +1263,5 @@
 			pointer->grab_flags = GF_EMPTY;
 			
-		} else if (within_client && (pointer->grab_flags == GF_EMPTY) && (bnum == 1)) {
+		} else if (within_client && (pointer->grab_flags == GF_EMPTY) && (btn_num == 1)) {
 
 			/* Bring the window to the foreground. */
@@ -1331,10 +1286,14 @@
 	}
 
-	return EOK;
-}
-
-static int comp_key_press(input_t *input, kbd_event_type_t type, keycode_t key,
-    keymod_t mods, wchar_t c)
-{
+	async_answer_0(iid, EOK);
+}
+
+static void comp_key_press(ipc_callid_t iid, ipc_call_t *icall)
+{
+	kbd_event_type_t type = IPC_GET_ARG1(*icall);
+	keycode_t key = IPC_GET_ARG2(*icall);
+	keymod_t mods = IPC_GET_ARG3(*icall);
+	wchar_t c = IPC_GET_ARG4(*icall);
+
 	bool win_transform = (mods & KM_ALT) && (
 	    key == KC_W || key == KC_S || key == KC_A || key == KC_D ||
@@ -1419,5 +1378,6 @@
 			if (event == NULL) {
 				fibril_mutex_unlock(&window_list_mtx);
-				return ENOMEM;
+				async_answer_0(iid, ENOMEM);
+				return;
 			}
 
@@ -1488,6 +1448,8 @@
 	} else if (win_close) {
 		window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
-		if (event == NULL)
-			return ENOMEM;
+		if (event == NULL) {
+			async_answer_0(iid, ENOMEM);
+			return;
+		}
 
 		link_initialize(&event->link);
@@ -1540,27 +1502,27 @@
 			switch (key) {
 			case KC_I:
-				vp->pos.x += 0;
-				vp->pos.y += -20;
+				vp->hpos += 0;
+				vp->vpos += -20;
 				break;
 			case KC_K:
-				vp->pos.x += 0;
-				vp->pos.y += 20;
+				vp->hpos += 0;
+				vp->vpos += 20;
 				break;
 			case KC_J:
-				vp->pos.x += -20;
-				vp->pos.y += 0;
+				vp->hpos += -20;
+				vp->vpos += 0;
 				break;
 			case KC_L:
-				vp->pos.x += 20;
-				vp->pos.y += 0;
+				vp->hpos += 20;
+				vp->vpos += 0;
 				break;
 			default:
-				vp->pos.x += 0;
-				vp->pos.y += 0;
+				vp->hpos += 0;
+				vp->vpos += 0;
 				break;
 			}
 			
-			sysarg_t x = vp->pos.x;
-			sysarg_t y = vp->pos.y;
+			sysarg_t x = vp->hpos;
+			sysarg_t y = vp->vpos;
 			sysarg_t width, height;
 			surface_get_resolution(vp->surface, &width, &height);
@@ -1632,6 +1594,8 @@
 	} else {
 		window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
-		if (event == NULL)
-			return ENOMEM;
+		if (event == NULL) {
+			async_answer_0(iid, ENOMEM);
+			return;
+		}
 
 		link_initialize(&event->link);
@@ -1645,25 +1609,9 @@
 	}
 
-	return EOK;
-}
-
-static int input_connect(const char *svc)
-{
-	async_sess_t *sess;
-	service_id_t dsid;
-
-	int rc = loc_service_get_id(svc, &dsid, 0);
-	if (rc != EOK) {
-		printf("%s: Input service %s not found\n", NAME, svc);
-		return rc;
-	}
-
-	sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
-	if (sess == NULL) {
-		printf("%s: Unable to connect to input service %s\n", NAME,
-		    svc);
-		return EIO;
-	}
-
+	async_answer_0(iid, EOK);
+}
+
+static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
 	fibril_mutex_lock(&pointer_list_mtx);
 	pointer_t *pointer = pointer_create();
@@ -1674,26 +1622,63 @@
 	fibril_mutex_unlock(&pointer_list_mtx);
 
-	if (pointer == NULL) {
-		printf("%s: Cannot create pointer.\n", NAME);
-		async_hangup(sess);
-		return ENOMEM;
-	}
-
-	rc = input_open(sess, &input_ev_ops, pointer, &input);
+	/* Ignore parameters, the connection is already opened. */
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			fibril_mutex_lock(&pointer_list_mtx);
+			if (pointer != NULL) {
+				list_remove(&pointer->link);
+				pointer_destroy(pointer);
+			}
+			fibril_mutex_unlock(&pointer_list_mtx);
+			async_hangup(input_sess);
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case INPUT_EVENT_KEY:
+			comp_key_press(callid, &call);
+			break;
+		case INPUT_EVENT_MOVE:
+			comp_mouse_move(pointer, callid, &call);
+			break;
+		case INPUT_EVENT_BUTTON:
+			comp_mouse_button(pointer, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+}
+
+static async_sess_t *input_connect(const char *svc)
+{
+	async_sess_t *sess;
+	service_id_t dsid;
+
+	int rc = loc_service_get_id(svc, &dsid, 0);
+	if (rc == EOK) {
+		sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
+		if (sess == NULL) {
+			printf("%s: Unable to connect to input service %s\n", NAME, svc);
+			return NULL;
+		}
+	} else
+		return NULL;
+
+	async_exch_t *exch = async_exchange_begin(sess);
+	rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL);
+	async_exchange_end(exch);
+
 	if (rc != EOK) {
 		async_hangup(sess);
-		printf("%s: Unable to communicate with service %s (%s)\n",
+		printf("%s: Unable to create callback connection to service %s (%s)\n",
 		    NAME, svc, str_error(rc));
-		return rc;
-	}
-
-	return EOK;
-}
-
-static void input_disconnect(void)
-{
-    	pointer_t *pointer = input->user;
-	input_close(input);
-	pointer_destroy(pointer);
+		return NULL;
+	}
+
+	return sess;
 }
 
@@ -1748,7 +1733,8 @@
 
 	/* Establish input bidirectional connection. */
-	rc = input_connect(input_svc);
-	if (rc != EOK)
-		return rc;
+	input_sess = input_connect(input_svc);
+	if (input_sess == NULL) {
+		return -1;
+	}
 
 	/* Create viewports and connect them to visualizers. */
@@ -1756,5 +1742,5 @@
 	rc = loc_category_get_id("visualizer", &cat_id, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
-		input_disconnect();
+		async_hangup(input_sess);
 		return -1;
 	}
@@ -1764,5 +1750,5 @@
 	rc = loc_category_get_svcs(cat_id, &svcs, &svcs_cnt);
 	if (rc != EOK || svcs_cnt == 0) {
-		input_disconnect();
+		async_hangup(input_sess);
 		return -1;
 	}
@@ -1780,5 +1766,5 @@
 	
 	if (list_empty(&viewport_list)) {
-		input_disconnect();
+		async_hangup(input_sess);
 		return -1;
 	}
