Index: uspace/srv/hid/compositor/compositor.c
===================================================================
--- uspace/srv/hid/compositor/compositor.c	(revision c4ebe025c2fab360da14b4704075168c94a51a2c)
+++ uspace/srv/hid/compositor/compositor.c	(revision 290a0f0bca64b949d48d6b8a5d58988fc13ad577)
@@ -573,5 +573,5 @@
 		pointer_t *pointer = list_get_instance(link, pointer_t, link);
 		if (pointer->id == pos_id) {
-			pointer->grab_flags = grab_flags;
+			pointer->grab_flags = pointer->pressed ? grab_flags : GF_EMPTY;
 			// TODO change pointer->state according to grab_flags
 			break;
@@ -646,4 +646,32 @@
 }
 
+static void comp_post_event_win(window_event_t *event, window_t *target)
+{
+	fibril_mutex_lock(&window_list_mtx);
+	window_t *window = NULL;
+	list_foreach(window_list, link) {
+		window = list_get_instance(link, window_t, link);
+		if (window == target) {
+			prodcons_produce(&window->queue, &event->link);
+		}
+	}
+	if (!window) {
+		free(event);
+	}
+	fibril_mutex_unlock(&window_list_mtx);
+}
+
+static void comp_post_event_top(window_event_t *event)
+{
+	fibril_mutex_lock(&window_list_mtx);
+	window_t *win = (window_t *) list_first(&window_list);
+	if (win) {
+		prodcons_produce(&win->queue, &event->link);
+	} else {
+		free(event);
+	}
+	fibril_mutex_unlock(&window_list_mtx);
+}
+
 static void comp_window_close(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
 {
@@ -651,5 +679,15 @@
 	fibril_mutex_lock(&window_list_mtx);
 	list_remove(&win->link);
+	window_t *win_focus = (window_t *) list_first(&window_list);
+	window_event_t *event_focus = (window_event_t *) malloc(sizeof(window_event_t));
+	if (event_focus) {
+		link_initialize(&event_focus->link);
+		event_focus->type = ET_WINDOW_FOCUS;
+	}
 	fibril_mutex_unlock(&window_list_mtx);
+
+	if (event_focus && win_focus) {
+		comp_post_event_win(event_focus, win_focus);
+	}
 
 	/* Calculate damage. */
@@ -735,8 +773,20 @@
 			}
 
+			window_t *win_unfocus = (window_t *) list_first(&window_list);
 			list_prepend(&win->link, &window_list);
+
+			window_event_t *event_unfocus = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event_unfocus) {
+				link_initialize(&event_unfocus->link);
+				event_unfocus->type = ET_WINDOW_UNFOCUS;
+			}
 			
 			async_answer_2(callid, EOK, win->in_dsid, win->out_dsid);
 			fibril_mutex_unlock(&window_list_mtx);
+			
+			if (event_unfocus && win_unfocus) {
+				comp_post_event_win(event_unfocus, win_unfocus);
+			}
+
 			return;
 		} else {
@@ -1058,16 +1108,4 @@
 }
 
-static void comp_post_event(window_event_t *event)
-{
-	fibril_mutex_lock(&window_list_mtx);
-	window_t *win = (window_t *) list_first(&window_list);
-	if (win) {
-		prodcons_produce(&win->queue, &event->link);
-	} else {
-		free(event);
-	}
-	fibril_mutex_unlock(&window_list_mtx);
-}
-
 static void comp_recalc_transform(window_t *win)
 {
@@ -1102,4 +1140,5 @@
 {
 	/* window_list_mtx locked by caller */
+	/* pointer_list_mtx locked by caller */
 
 	int dx = pointer->accum.x;
@@ -1181,4 +1220,7 @@
     desktop_rect_t *rect1, desktop_rect_t *rect2, desktop_rect_t *rect3, desktop_rect_t *rect4)
 {
+	/* window_list_mtx locked by caller */
+	/* pointer_list_mtx locked by caller */
+
 	int dx = pointer->accum_ghost.x;
 	int dy = pointer->accum_ghost.y;
@@ -1336,4 +1378,5 @@
 
 	fibril_mutex_lock(&window_list_mtx);
+	fibril_mutex_lock(&pointer_list_mtx);
 	window_t *top = (window_t *) list_first(&window_list);
 	if (top && top->surface) {
@@ -1347,8 +1390,8 @@
 			within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
 			    top->transform, width, height, &point_x, &point_y);
-			fibril_mutex_unlock(&window_list_mtx);
-
+
+			window_event_t *event = NULL;
 			if (within_client) {
-				window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
+				event = (window_event_t *) malloc(sizeof(window_event_t));
 				if (event) {
 					link_initialize(&event->link);
@@ -1359,7 +1402,14 @@
 					event->data.pos.hpos = point_x;
 					event->data.pos.vpos = point_y;
-					comp_post_event(event);
 				}
 			}
+
+			fibril_mutex_unlock(&pointer_list_mtx);
+			fibril_mutex_unlock(&window_list_mtx);
+
+			if (event) {
+				comp_post_event_top(event);
+			}
+
 		} else {
 			/* Pointer is grabbed by top-level window action. */
@@ -1385,4 +1435,5 @@
 			comp_window_animate(pointer, top, &x, &y, &width, &height);
 #endif
+			fibril_mutex_unlock(&pointer_list_mtx);
 			fibril_mutex_unlock(&window_list_mtx);
 #if ANIMATE_WINDOW_TRANSFORMS == 0
@@ -1397,4 +1448,5 @@
 		}
 	} else {
+		fibril_mutex_unlock(&pointer_list_mtx);
 		fibril_mutex_unlock(&window_list_mtx);
 	}
@@ -1408,4 +1460,5 @@
 
 	fibril_mutex_lock(&window_list_mtx);
+	fibril_mutex_lock(&pointer_list_mtx);
 	window_t *win = NULL;
 	sysarg_t point_x = 0;
@@ -1430,9 +1483,12 @@
 	window_t *top = (window_t *) list_first(&window_list);
 	if (!win || !top) {
+		fibril_mutex_unlock(&pointer_list_mtx);
 		fibril_mutex_unlock(&window_list_mtx);
 		return EOK;
 	}
 
-	window_event_t *event = NULL;
+	window_event_t *event_top = NULL;
+	window_event_t *event_unfocus = NULL;
+	window_t *win_unfocus = NULL;
 	sysarg_t dmg_x, dmg_y;
 	sysarg_t dmg_width = 0;
@@ -1450,6 +1506,12 @@
 		/* Bring the window to the foreground. */
 		if ((win != top) && within_client) {
+			win_unfocus = (window_t *) list_first(&window_list);
 			list_remove(&win->link);
 			list_prepend(&win->link, &window_list);
+			event_unfocus = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event_unfocus) {
+				link_initialize(&event_unfocus->link);
+				event_unfocus->type = ET_WINDOW_UNFOCUS;
+			}
 			comp_coord_bounding_rect(0, 0, width, height, win->transform,
 			    &dmg_x, &dmg_y, &dmg_width, &dmg_height);
@@ -1458,13 +1520,13 @@
 		/* Notify top-level window about mouse press. */
 		if (within_client) {
-			event = (window_event_t *) malloc(sizeof(window_event_t));
-			if (event) {
-				link_initialize(&event->link);
-				event->type = ET_POSITION_EVENT;
-				event->data.pos.pos_id = pointer->id;
-				event->data.pos.type = POS_PRESS;
-				event->data.pos.btn_num = bnum;
-				event->data.pos.hpos = point_x;
-				event->data.pos.vpos = point_y;
+			event_top = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event_top) {
+				link_initialize(&event_top->link);
+				event_top->type = ET_POSITION_EVENT;
+				event_top->data.pos.pos_id = pointer->id;
+				event_top->data.pos.type = POS_PRESS;
+				event_top->data.pos.btn_num = bnum;
+				event_top->data.pos.hpos = point_x;
+				event_top->data.pos.vpos = point_y;
 			}
 			pointer->grab_flags = GF_EMPTY;
@@ -1501,8 +1563,8 @@
 
 			/* Commit proper resize action. */
-			event = (window_event_t *) malloc(sizeof(window_event_t));
-			if (event) {
-				link_initialize(&event->link);
-				event->type = ET_WINDOW_RESIZE;
+			event_top = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event_top) {
+				link_initialize(&event_top->link);
+				event_top->type = ET_WINDOW_RESIZE;
 
 				int dx = (int) (((double) width) * (scale_back_x - 1.0));
@@ -1510,15 +1572,15 @@
 
 				if (pointer->grab_flags & GF_RESIZE_X) {
-					event->data.rsz.width =
+					event_top->data.rsz.width =
 						((((int) width) + dx) >= 0) ? (width + dx) : 0;
 				} else {
-					event->data.rsz.width = width;
+					event_top->data.rsz.width = width;
 				}
 
 				if (pointer->grab_flags & GF_RESIZE_Y) {
-					event->data.rsz.height =
+					event_top->data.rsz.height =
 						((((int) height) + dy) >= 0) ? (height + dy) : 0;
 				} else {
-					event->data.rsz.height = height;
+					event_top->data.rsz.height = height;
 				}
 			}
@@ -1529,13 +1591,13 @@
 			
 			/* Notify top-level window about mouse release. */
-			event = (window_event_t *) malloc(sizeof(window_event_t));
-			if (event) {
-				link_initialize(&event->link);
-				event->type = ET_POSITION_EVENT;
-				event->data.pos.pos_id = pointer->id;
-				event->data.pos.type = POS_RELEASE;
-				event->data.pos.btn_num = bnum;
-				event->data.pos.hpos = point_x;
-				event->data.pos.vpos = point_y;
+			event_top = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event_top) {
+				link_initialize(&event_top->link);
+				event_top->type = ET_POSITION_EVENT;
+				event_top->data.pos.pos_id = pointer->id;
+				event_top->data.pos.type = POS_RELEASE;
+				event_top->data.pos.btn_num = bnum;
+				event_top->data.pos.hpos = point_x;
+				event_top->data.pos.vpos = point_y;
 			}
 			pointer->grab_flags = GF_EMPTY;
@@ -1547,4 +1609,5 @@
 	}
 
+	fibril_mutex_unlock(&pointer_list_mtx);
 	fibril_mutex_unlock(&window_list_mtx);
 
@@ -1560,6 +1623,10 @@
 	}
 
-	if (event) {
-		comp_post_event(event);
+	if (event_unfocus && win_unfocus) {
+		comp_post_event_win(event_unfocus, win_unfocus);
+	}
+
+	if (event_top) {
+		comp_post_event_top(event_top);
 	}
 
@@ -1685,5 +1752,5 @@
 
 			fibril_mutex_unlock(&window_list_mtx);
-			comp_post_event(event);
+			comp_post_event_top(event);
 		} else {
 			fibril_mutex_unlock(&window_list_mtx);
@@ -1727,5 +1794,5 @@
 		event->type = ET_WINDOW_CLOSE;
 
-		comp_post_event(event);
+		comp_post_event_top(event);
 	} else if (win_switch) {
 		fibril_mutex_lock(&window_list_mtx);
@@ -1735,4 +1802,16 @@
 			list_append(&win1->link, &window_list);
 			window_t *win2 = (window_t *) list_first(&window_list);
+
+			window_event_t *event1 = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event1) {
+				link_initialize(&event1->link);
+				event1->type = ET_WINDOW_UNFOCUS;
+			}
+
+			window_event_t *event2 = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event2) {
+				link_initialize(&event2->link);
+				event2->type = ET_WINDOW_FOCUS;
+			}
 
 			sysarg_t x1 = 0;
@@ -1763,4 +1842,13 @@
 
 			fibril_mutex_unlock(&window_list_mtx);
+
+			if (event1 && win1) {
+				comp_post_event_win(event1, win1);
+			}
+
+			if (event2 && win2) {
+				comp_post_event_win(event2, win2);
+			}
+
 			comp_damage(x, y, width, height);
 		} else {
@@ -1875,5 +1963,5 @@
 		event->data.kbd.c = c;
 
-		comp_post_event(event);
+		comp_post_event_top(event);
 	}
 
@@ -1926,5 +2014,5 @@
 static void input_disconnect(void)
 {
-    	pointer_t *pointer = input->user;
+	pointer_t *pointer = input->user;
 	input_close(input);
 	pointer_destroy(pointer);
