Index: kernel/arch/amd64/src/fpu_context.c
===================================================================
--- kernel/arch/amd64/src/fpu_context.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ kernel/arch/amd64/src/fpu_context.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -57,4 +57,6 @@
 {
 	/* TODO: Zero all SSE, MMX etc. registers */
+	/* Default value of SCR register is 0x1f80,
+	 * it masks all FPU exceptions*/
 	asm volatile (
 		"fninit\n"
Index: kernel/arch/ia32/src/fpu_context.c
===================================================================
--- kernel/arch/ia32/src/fpu_context.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ kernel/arch/ia32/src/fpu_context.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -37,4 +37,31 @@
 #include <arch.h>
 #include <cpu.h>
+
+
+/** x87 FPU scr values (P3+ MMX2) */
+enum {
+	X87_FLUSH_ZERO_FLAG = (1 << 15),
+	X87_ROUND_CONTROL_MASK = (0x3 << 13),
+	x87_ROUND_TO_NEAREST_EVEN = (0x0 << 13),
+	X87_ROUND_DOWN_TO_NEG_INF = (0x1 << 13),
+	X87_ROUND_UP_TO_POS_INF = (0x2 << 13),
+	X87_ROUND_TO_ZERO = (0x3 << 13),
+	X87_PRECISION_MASK = (1 << 12),
+	X87_UNDERFLOW_MASK = (1 << 11),
+	X87_OVERFLOW_MASK = (1 << 10),
+	X87_ZERO_DIV_MASK = (1 << 9),
+	X87_DENORMAL_OP_MASK = (1 << 8),
+	X87_INVALID_OP_MASK = (1 << 7),
+	X87_DENOM_ZERO_FLAG = (1 << 6),
+	X87_PRECISION_EXC_FLAG = (1 << 5),
+	X87_UNDERFLOW_EXC_FLAG = (1 << 4),
+	X87_OVERFLOW_EXC_FLAG = (1 << 3),
+	X87_ZERO_DIV_EXC_FLAG = (1 << 2),
+	X87_DENORMAL_EXC_FLAG = (1 << 1),
+	X87_INVALID_OP_EXC_FLAG = (1 << 0),
+
+	X87_ALL_MASK = X87_PRECISION_MASK | X87_UNDERFLOW_MASK | X87_OVERFLOW_MASK | X87_ZERO_DIV_MASK | X87_DENORMAL_OP_MASK | X87_INVALID_OP_MASK,
+};
+
 
 typedef void (*fpu_context_function)(fpu_context_t *fctx);
@@ -98,4 +125,5 @@
 }
 
+/** Initialize x87 FPU. Mask all exceptions. */
 void fpu_init()
 {
@@ -111,5 +139,5 @@
 		"ldmxcsr %[help0]\n"
 		: [help0] "+m" (help0), [help1] "+r" (help1)
-		: [magic] "i" (0x1f80)
+		: [magic] "i" (X87_ALL_MASK)
 	);
 }
Index: uspace/app/vdemo/vdemo.c
===================================================================
--- uspace/app/vdemo/vdemo.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/app/vdemo/vdemo.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -110,5 +110,5 @@
 {
 	if (argc >= 2) {
-		window_t *main_window = window_open(argv[1], true, true, "vdemo");
+		window_t *main_window = window_open(argv[1], true, true, "vdemo", 0, 0);
 		if (!main_window) {
 			printf("Cannot open main window.\n");
Index: uspace/app/vlaunch/vlaunch.c
===================================================================
--- uspace/app/vlaunch/vlaunch.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/app/vlaunch/vlaunch.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -98,5 +98,5 @@
 	
 	winreg = argv[1];
-	window_t *main_window = window_open(argv[1], true, true, "vlaunch");
+	window_t *main_window = window_open(argv[1], true, true, "vlaunch", 0, 0);
 	if (!main_window) {
 		printf("Cannot open main window.\n");
Index: uspace/app/vterm/vterm.c
===================================================================
--- uspace/app/vterm/vterm.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/app/vterm/vterm.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -49,5 +49,5 @@
 	}
 	
-	window_t *main_window = window_open(argv[1], true, true, "vterm");
+	window_t *main_window = window_open(argv[1], true, true, "vterm", 0, 0);
 	if (!main_window) {
 		printf("%s: Cannot open main window.\n", NAME);
Index: uspace/drv/fb/kfb/port.c
===================================================================
--- uspace/drv/fb/kfb/port.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/drv/fb/kfb/port.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -163,7 +163,7 @@
 		/* Faster damage routine ignoring offsets. */
 		for (sysarg_t y = y0; y < height + y0; ++y) {
+			pixel_t *pixel = pixelmap_pixel_at(map, x0, y);
 			for (sysarg_t x = x0; x < width + x0; ++x) {
-				kfb.pixel2visual(kfb.addr + FB_POS(x, y),
-				    *pixelmap_pixel_at(map, x, y));
+				kfb.pixel2visual(kfb.addr + FB_POS(x, y), *pixel++);
 			}
 		}
Index: uspace/lib/c/generic/io/window.c
===================================================================
--- uspace/lib/c/generic/io/window.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/c/generic/io/window.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -40,8 +40,9 @@
 #include <stdio.h>
 
-int win_register(async_sess_t *sess, service_id_t *in, service_id_t *out)
+int win_register(async_sess_t *sess, service_id_t *in, service_id_t *out, 
+    sysarg_t x_offset, sysarg_t y_offset)
 {
 	async_exch_t *exch = async_exchange_begin(sess);
-	int ret = async_req_0_2(exch, WINDOW_REGISTER, in, out);
+	int ret = async_req_2_2(exch, WINDOW_REGISTER, x_offset, y_offset, in, out);
 	async_exchange_end(exch);
 
Index: uspace/lib/c/generic/stdlib.c
===================================================================
--- uspace/lib/c/generic/stdlib.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/c/generic/stdlib.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -39,10 +39,10 @@
 long int random(void)
 {
-	return glbl_seed = ((1366*glbl_seed + 150889) % RAND_MAX);
+	return glbl_seed = ((1366 * glbl_seed + 150889) % RAND_MAX);
 }
 
 void srandom(unsigned int seed)
 {
-	glbl_seed = seed;
+	glbl_seed = seed % RAND_MAX;
 }
 
Index: uspace/lib/c/include/io/pixel.h
===================================================================
--- uspace/lib/c/include/io/pixel.h	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/c/include/io/pixel.h	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -42,4 +42,6 @@
 	((channel) >> (8 - (bits)))
 
+#define INVERT(pixel) ((pixel) ^ 0x00ffffff)
+
 #define ALPHA(pixel)  ((pixel) >> 24)
 #define RED(pixel)    (((pixel) & 0x00ff0000) >> 16)
Index: uspace/lib/c/include/io/pixelmap.h
===================================================================
--- uspace/lib/c/include/io/pixelmap.h	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/c/include/io/pixelmap.h	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -52,7 +52,11 @@
     sysarg_t y)
 {
-	size_t offset = y * pixelmap->width + x;
-	pixel_t *pixel = pixelmap->data + offset;
-	return pixel;
+	if (x < pixelmap->width && y < pixelmap->height) {
+		size_t offset = y * pixelmap->width + x;
+		pixel_t *pixel = pixelmap->data + offset;
+		return pixel;
+	} else {
+		return NULL;
+	}
 }
 
Index: uspace/lib/c/include/io/window.h
===================================================================
--- uspace/lib/c/include/io/window.h	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/c/include/io/window.h	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -71,4 +71,6 @@
 	ET_POSITION_EVENT,
 	ET_SIGNAL_EVENT,
+	ET_WINDOW_FOCUS,
+	ET_WINDOW_UNFOCUS,
 	ET_WINDOW_RESIZE,
 	ET_WINDOW_REFRESH,
@@ -100,5 +102,5 @@
 } window_grab_flags_t;
 
-extern int win_register(async_sess_t *, service_id_t *, service_id_t *);
+extern int win_register(async_sess_t *, service_id_t *, service_id_t *, sysarg_t, sysarg_t);
 
 extern int win_get_event(async_sess_t *, window_event_t *);
Index: uspace/lib/draw/drawctx.c
===================================================================
--- uspace/lib/draw/drawctx.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/draw/drawctx.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -129,26 +129,48 @@
 	}
 
-	bool clipped = false;
-	bool masked = false;
-
-	for (sysarg_t _y = y; _y < y + height; ++_y) {
-		for (sysarg_t _x = x; _x < x + width; ++_x) {
-			if (context->shall_clip) {
-				clipped = _x < context->clip_x && _x >= context->clip_width
-				    && _y < context->clip_y && _y >= context->clip_height;
-			}
-			
-			if (context->mask) {
-				pixel_t p = surface_get_pixel(context->mask, _x, _y);
-				masked = p > 0 ? false : true;
-			}
-
-			if (!clipped && !masked) {
-				pixel_t p_src = source_determine_pixel(context->source, _x, _y);
-				pixel_t p_dst = surface_get_pixel(context->surface, _x, _y);
-				pixel_t p_res = context->compose(p_src, p_dst);
-				surface_put_pixel(context->surface, _x, _y, p_res);
+	bool transfer_fast = source_is_fast(context->source)
+	    && (context->shall_clip == false)
+	    && (context->mask == NULL)
+	    && (context->compose == compose_src || context->compose == compose_over);
+
+	if (transfer_fast) {
+
+		for (sysarg_t _y = y; _y < y + height; ++_y) {
+			pixel_t *src = source_direct_access(context->source, x, _y);
+			pixel_t *dst = pixelmap_pixel_at(surface_pixmap_access(context->surface), x, _y);
+			if (src && dst) {
+				sysarg_t count = width;
+				while (count-- != 0) {
+					*dst++ = *src++;
+				}
 			}
 		}
+		surface_add_damaged_region(context->surface, x, y, width, height);
+
+	} else {
+
+		bool clipped = false;
+		bool masked = false;
+		for (sysarg_t _y = y; _y < y + height; ++_y) {
+			for (sysarg_t _x = x; _x < x + width; ++_x) {
+				if (context->shall_clip) {
+					clipped = _x < context->clip_x && _x >= context->clip_width
+					    && _y < context->clip_y && _y >= context->clip_height;
+				}
+
+				if (context->mask) {
+					pixel_t p = surface_get_pixel(context->mask, _x, _y);
+					masked = p > 0 ? false : true;
+				}
+
+				if (!clipped && !masked) {
+					pixel_t p_src = source_determine_pixel(context->source, _x, _y);
+					pixel_t p_dst = surface_get_pixel(context->surface, _x, _y);
+					pixel_t p_res = context->compose(p_src, p_dst);
+					surface_put_pixel(context->surface, _x, _y, p_res);
+				}
+			}
+		}
+
 	}
 }
Index: uspace/lib/draw/source.c
===================================================================
--- uspace/lib/draw/source.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/draw/source.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -90,4 +90,24 @@
 }
 
+bool source_is_fast(source_t *source)
+{
+	return (source->mask == NULL)
+	    && (source->alpha == (pixel_t) PIXEL(255, 0, 0, 0))
+	    && (source->texture != NULL)
+	    && (source->texture_tile == false)
+	    && transform_is_fast(&source->transform);
+}
+
+pixel_t *source_direct_access(source_t *source, double x, double y)
+{
+	assert(source_is_fast(source));
+
+	long _x = (long) (x + source->transform.m[0][2]);
+	long _y = (long) (y + source->transform.m[1][2]);
+
+	return pixelmap_pixel_at(
+	    surface_pixmap_access(source->texture), (sysarg_t) _x, (sysarg_t) _y);
+}
+
 pixel_t source_determine_pixel(source_t *source, double x, double y)
 {
Index: uspace/lib/draw/source.h
===================================================================
--- uspace/lib/draw/source.h	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/draw/source.h	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -71,4 +71,6 @@
 extern void source_set_mask(source_t *, surface_t *, bool);
 
+extern bool source_is_fast(source_t *);
+extern pixel_t *source_direct_access(source_t *, double, double);
 extern pixel_t source_determine_pixel(source_t *, double, double);
 
Index: uspace/lib/draw/surface.c
===================================================================
--- uspace/lib/draw/surface.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/draw/surface.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -143,4 +143,17 @@
 }
 
+void surface_add_damaged_region(surface_t *surface, surface_coord_t x, surface_coord_t y,
+    surface_coord_t width, surface_coord_t height)
+{
+	surface->dirty_x_lo = surface->dirty_x_lo > x ? x : surface->dirty_x_lo;
+	surface->dirty_y_lo = surface->dirty_y_lo > y ? y : surface->dirty_y_lo;
+
+	surface_coord_t x_hi = x + width - 1;
+	surface_coord_t y_hi = y + height - 1;
+
+	surface->dirty_x_hi = surface->dirty_x_hi < x_hi ? x_hi : surface->dirty_x_hi;
+	surface->dirty_y_hi = surface->dirty_y_hi < y_hi ? y_hi : surface->dirty_y_hi;
+}
+
 void surface_reset_damaged_region(surface_t *surface)
 {
@@ -158,16 +171,10 @@
 	surface->dirty_y_hi = surface->dirty_y_hi < y ? y : surface->dirty_y_hi;
 
-	if (x < surface->pixmap.width && y < surface->pixmap.height) {
-		pixelmap_put_pixel(&surface->pixmap, x, y, pixel);
-	}
+	pixelmap_put_pixel(&surface->pixmap, x, y, pixel);
 }
 
 pixel_t surface_get_pixel(surface_t *surface, surface_coord_t x, surface_coord_t y)
 {
-	if (x < surface->pixmap.width && y < surface->pixmap.height) {
-		return pixelmap_get_pixel(&surface->pixmap, x, y);
-	} else {
-		return 0;
-	}
+	return pixelmap_get_pixel(&surface->pixmap, x, y);
 }
 
Index: uspace/lib/draw/surface.h
===================================================================
--- uspace/lib/draw/surface.h	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/draw/surface.h	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -61,4 +61,6 @@
 extern void surface_get_damaged_region(surface_t *, surface_coord_t *, surface_coord_t *,
     surface_coord_t *, surface_coord_t *);
+extern void surface_add_damaged_region(surface_t *, surface_coord_t , surface_coord_t ,
+    surface_coord_t , surface_coord_t );
 extern void surface_reset_damaged_region(surface_t *);
 
Index: uspace/lib/gui/terminal.c
===================================================================
--- uspace/lib/gui/terminal.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/gui/terminal.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -196,15 +196,16 @@
 	uint16_t glyph = fb_font_glyph(field->ch);
 	
-	// FIXME: This font drawing routine is shamelessly
-	//        suboptimal. It should be optimized for
-	//        aligned memory transfers, etc.
-	
 	for (unsigned int y = 0; y < FONT_SCANLINES; y++) {
-		for (unsigned int x = 0; x < FONT_WIDTH; x++) {
-			pixel_t pixel =
-			    (fb_font[glyph][y] & (1 << (7 - x))) ? fgcolor : bgcolor;
-			surface_put_pixel(surface, bx + x, by + y, pixel);
+		pixel_t *dst = pixelmap_pixel_at(
+		    surface_pixmap_access(surface), bx, by + y);
+		pixel_t *dst_max = pixelmap_pixel_at(
+		    surface_pixmap_access(surface), bx + FONT_WIDTH - 1, by + y);
+		if (!dst || !dst_max) continue;
+		int count = FONT_WIDTH;
+		while (count-- != 0) {
+			*dst++ = (fb_font[glyph][y] & (1 << count)) ? fgcolor : bgcolor;
 		}
 	}
+	surface_add_damaged_region(surface, bx, by, FONT_WIDTH, FONT_SCANLINES);
 }
 
Index: uspace/lib/gui/window.c
===================================================================
--- uspace/lib/gui/window.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/gui/window.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -66,6 +66,8 @@
 
 static pixel_t border_color = PIXEL(255, 0, 0, 0);
-static pixel_t header_bgcolor = PIXEL(255, 25, 25, 112);
-static pixel_t header_fgcolor = PIXEL(255, 255, 255, 255);
+static pixel_t header_bg_focus_color = PIXEL(255, 25, 25, 112);
+static pixel_t header_fg_focus_color = PIXEL(255, 255, 255, 255);
+static pixel_t header_bg_unfocus_color = PIXEL(255, 70, 130, 180);
+static pixel_t header_fg_unfocus_color = PIXEL(255, 255, 255, 255);
 
 static void paint_internal(widget_t *w)
@@ -94,5 +96,6 @@
 	    w->vpos + w->height - border_thickness, w->width, border_thickness);
 
-	source_set_color(&source, header_bgcolor);
+	source_set_color(&source, 
+	    w->window->is_focused ? header_bg_focus_color : header_bg_unfocus_color);
 	drawctx_transfer(&drawctx,
 	    w->hpos + border_thickness, w->vpos + border_thickness,
@@ -106,5 +109,6 @@
 	char cls_pict[] = "x";
 	font_get_box(&font, cls_pict, &cls_width, &cls_height);
-	source_set_color(&source, header_fgcolor);
+	source_set_color(&source, 
+	    w->window->is_focused ? header_fg_focus_color : header_fg_unfocus_color);
 	sysarg_t cls_x = ((close_width - cls_width) / 2) + w->hpos + w->width -
 	    border_thickness - close_width;
@@ -447,4 +451,8 @@
 			break;
 		case ET_POSITION_EVENT:
+			if (!win->is_focused) {
+				win->is_focused = true;
+				handle_refresh(win);
+			}
 			deliver_position_event(win, event->data.pos);
 			break;
@@ -454,4 +462,16 @@
 		case ET_WINDOW_RESIZE:
 			handle_resize(win, event->data.rsz.width, event->data.rsz.height);
+			break;
+		case ET_WINDOW_FOCUS:
+			if (!win->is_focused) {
+				win->is_focused = true;
+				handle_refresh(win);
+			}
+			break;
+		case ET_WINDOW_UNFOCUS:
+			if (win->is_focused) {
+				win->is_focused = false;
+				handle_refresh(win);
+			}
 			break;
 		case ET_WINDOW_REFRESH:
@@ -514,5 +534,6 @@
 }
 
-window_t *window_open(char *winreg, bool is_main, bool is_decorated, const char *caption)
+window_t *window_open(char *winreg, bool is_main, bool is_decorated, 
+    const char *caption, sysarg_t x_offset, sysarg_t y_offset)
 {
 	int rc;
@@ -525,4 +546,5 @@
 	win->is_main = is_main;
 	win->is_decorated = is_decorated;
+	win->is_focused = true;
 	prodcons_initialize(&win->events);
 	fibril_mutex_initialize(&win->guard);
@@ -557,5 +579,5 @@
 	service_id_t out_dsid;
 	
-	rc = win_register(reg_sess, &in_dsid, &out_dsid);
+	rc = win_register(reg_sess, &in_dsid, &out_dsid, x_offset, y_offset);
 	async_hangup(reg_sess);
 	if (rc != EOK) {
Index: uspace/lib/gui/window.h
===================================================================
--- uspace/lib/gui/window.h	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/gui/window.h	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -50,4 +50,5 @@
 	bool is_main; /**< True for the main window of the application. */
 	bool is_decorated; /**< True if the window decorations should be rendered. */
+	bool is_focused; /**< True for the top level window of the desktop. */
 	char *caption; /**< Text title of the window header. */
 	async_sess_t *isess; /**< Input events from compositor. */
@@ -65,5 +66,5 @@
  * If the window is declared as main, its closure causes termination of the
  * whole application. Note that opened window does not have any surface yet. */
-extern window_t *window_open(char *, bool, bool, const char *);
+extern window_t *window_open(char *, bool, bool, const char *, sysarg_t, sysarg_t);
 
 /**
Index: uspace/lib/softrend/filter.c
===================================================================
--- uspace/lib/softrend/filter.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/softrend/filter.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -44,6 +44,4 @@
 		_x %= pixmap->width;
 		_y %= pixmap->height;
-	} else if (_x < 0 || _x >= (long) pixmap->width || _y < 0 || _y >= (long) pixmap->height) {
-		return 0;
 	}
 
Index: uspace/lib/softrend/transform.c
===================================================================
--- uspace/lib/softrend/transform.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/softrend/transform.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -136,4 +136,12 @@
 }
 
+bool transform_is_fast(transform_t *t)
+{
+	return (t->m[0][0] == 1) && (t->m[0][1] == 0)
+	    && (t->m[1][0] == 0) && (t->m[1][1] == 1)
+	    && ((t->m[0][2] - ((long) t->m[0][2])) == 0.0)
+	    && ((t->m[1][2] - ((long) t->m[1][2])) == 0.0);
+}
+
 void transform_apply_linear(const transform_t *t, double *x, double *y)
 {
Index: uspace/lib/softrend/transform.h
===================================================================
--- uspace/lib/softrend/transform.h	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/lib/softrend/transform.h	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -37,4 +37,6 @@
 #define SOFTREND_TRANSFORM_H_
 
+#include <bool.h>
+
 #ifndef PI
 #define PI 3.141592653589793
@@ -53,4 +55,6 @@
 extern void transform_rotate(transform_t *, double);
 
+extern bool transform_is_fast(transform_t *);
+
 extern void transform_apply_linear(const transform_t *, double *, double *);
 extern void transform_apply_affine(const transform_t *, double *, double *);
Index: uspace/srv/hid/compositor/compositor.c
===================================================================
--- uspace/srv/hid/compositor/compositor.c	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/srv/hid/compositor/compositor.c	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -90,21 +90,4 @@
 typedef struct {
 	link_t link;
-	sysarg_t id;
-	uint8_t state;
-	desktop_point_t pos;
-	sysarg_t btn_num;
-	desktop_point_t btn_pos;
-	desktop_vector_t accum;
-	sysarg_t grab_flags;
-	bool pressed;
-	cursor_t cursor;
-} pointer_t;
-
-static sysarg_t pointer_id = 0;
-static FIBRIL_MUTEX_INITIALIZE(pointer_list_mtx);
-static LIST_INITIALIZE(pointer_list);
-
-typedef struct {
-	link_t link;
 	service_id_t in_dsid;
 	service_id_t out_dsid;
@@ -129,4 +112,23 @@
 typedef struct {
 	link_t link;
+	sysarg_t id;
+	uint8_t state;
+	desktop_point_t pos;
+	sysarg_t btn_num;
+	desktop_point_t btn_pos;
+	desktop_vector_t accum;
+	sysarg_t grab_flags;
+	bool pressed;
+	cursor_t cursor;
+	window_t ghost;
+	desktop_vector_t accum_ghost;
+} pointer_t;
+
+static sysarg_t pointer_id = 0;
+static FIBRIL_MUTEX_INITIALIZE(pointer_list_mtx);
+static LIST_INITIALIZE(pointer_list);
+
+typedef struct {
+	link_t link;
 	service_id_t dsid;
 	vslmode_t mode;
@@ -181,4 +183,17 @@
 	cursor_init(&p->cursor, CURSOR_DECODER_EMBEDDED, NULL);
 
+	/* Ghost window for transformation animation. */
+	transform_identity(&p->ghost.transform);
+	transform_translate(&p->ghost.transform, coord_origin, coord_origin);
+	p->ghost.dx = coord_origin;
+	p->ghost.dy = coord_origin;
+	p->ghost.fx = 1;
+	p->ghost.fy = 1;
+	p->ghost.angle = 0;
+	p->ghost.opacity = 255;
+	p->ghost.surface = NULL;
+	p->accum_ghost.x = 0;
+	p->accum_ghost.y = 0;
+
 	return p;
 }
@@ -192,5 +207,5 @@
 }
 
-static window_t *window_create()
+static window_t *window_create(sysarg_t x_offset, sysarg_t y_offset)
 {
 	window_t *win = (window_t *) malloc(sizeof(window_t));
@@ -202,7 +217,8 @@
 	prodcons_initialize(&win->queue);
 	transform_identity(&win->transform);
-	transform_translate(&win->transform, coord_origin, coord_origin);
-	win->dx = coord_origin;
-	win->dy = coord_origin;
+	transform_translate(&win->transform, 
+	    coord_origin + x_offset, coord_origin + y_offset);
+	win->dx = coord_origin + x_offset;
+	win->dy = coord_origin + y_offset;
 	win->fx = 1;
 	win->fy = 1;
@@ -267,22 +283,27 @@
     sysarg_t *x_out, sysarg_t *y_out, sysarg_t *w_out, sysarg_t *h_out)
 {
-	sysarg_t x[4];
-	sysarg_t y[4];
-	comp_coord_from_client(x_in, y_in, win_trans, &x[0], &y[0]);
-	comp_coord_from_client(x_in + w_in, y_in, win_trans, &x[1], &y[1]);
-	comp_coord_from_client(x_in + w_in, y_in + h_in, win_trans, &x[2], &y[2]);
-	comp_coord_from_client(x_in, y_in + h_in, win_trans, &x[3], &y[3]);
-	(*x_out) = x[0];
-	(*y_out) = y[0];
-	(*w_out) = x[0];
-	(*h_out) = y[0];
-	for (int i = 1; i < 4; ++i) {
-		(*x_out) = (x[i] < (*x_out)) ? x[i] : (*x_out);
-		(*y_out) = (y[i] < (*y_out)) ? y[i] : (*y_out);
-		(*w_out) = (x[i] > (*w_out)) ? x[i] : (*w_out);
-		(*h_out) = (y[i] > (*h_out)) ? y[i] : (*h_out);
-	}
-	(*w_out) -= (*x_out);
-	(*h_out) -= (*y_out);
+	if (w_in > 0 && h_in > 0) {
+		sysarg_t x[4];
+		sysarg_t y[4];
+		comp_coord_from_client(x_in, y_in, win_trans, &x[0], &y[0]);
+		comp_coord_from_client(x_in + w_in - 1, y_in, win_trans, &x[1], &y[1]);
+		comp_coord_from_client(x_in + w_in - 1, y_in + h_in - 1, win_trans, &x[2], &y[2]);
+		comp_coord_from_client(x_in, y_in + h_in - 1, win_trans, &x[3], &y[3]);
+		(*x_out) = x[0];
+		(*y_out) = y[0];
+		(*w_out) = x[0];
+		(*h_out) = y[0];
+		for (int i = 1; i < 4; ++i) {
+			(*x_out) = (x[i] < (*x_out)) ? x[i] : (*x_out);
+			(*y_out) = (y[i] < (*y_out)) ? y[i] : (*y_out);
+			(*w_out) = (x[i] > (*w_out)) ? x[i] : (*w_out);
+			(*h_out) = (y[i] > (*h_out)) ? y[i] : (*h_out);
+		}
+		(*w_out) = (*w_out) - (*x_out) + 1;
+		(*h_out) = (*h_out) - (*y_out) + 1;
+	} else {
+		(*w_out) = 0;
+		(*h_out) = 0;
+	}
 }
 
@@ -309,8 +330,13 @@
 			/* 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) {
-					surface_put_pixel(vp->surface, x, y, bg_color);
+				pixel_t *dst = pixelmap_pixel_at(
+				    surface_pixmap_access(vp->surface), x_dmg_vp - vp->pos.x, y);
+				sysarg_t count = w_dmg_vp;
+				while (count-- != 0) {
+					*dst++ = bg_color;
 				}
 			}
+			surface_add_damaged_region(vp->surface,
+			    x_dmg_vp - vp->pos.x, y_dmg_vp - vp->pos.y, w_dmg_vp, h_dmg_vp);
 
 			transform_t transform;
@@ -363,4 +389,80 @@
 			list_foreach(pointer_list, link) {
 
+				pointer_t *ptr = list_get_instance(link, pointer_t, link);
+				if (ptr->ghost.surface) {
+
+					sysarg_t x_bnd_ghost, y_bnd_ghost, w_bnd_ghost, h_bnd_ghost;
+					sysarg_t x_dmg_ghost, y_dmg_ghost, w_dmg_ghost, h_dmg_ghost;
+					surface_get_resolution(ptr->ghost.surface, &w_bnd_ghost, &h_bnd_ghost);
+					comp_coord_bounding_rect(0, 0, w_bnd_ghost, h_bnd_ghost, ptr->ghost.transform,
+					    &x_bnd_ghost, &y_bnd_ghost, &w_bnd_ghost, &h_bnd_ghost);
+					bool isec_ghost = rectangle_intersect(
+					    x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp,
+					    x_bnd_ghost, y_bnd_ghost, w_bnd_ghost, h_bnd_ghost,
+					    &x_dmg_ghost, &y_dmg_ghost, &w_dmg_ghost, &h_dmg_ghost);
+
+					if (isec_ghost) {
+						/* FIXME: Ghost is currently drawn based on the bounding
+						 * rectangle of the window, which is sufficient as long
+						 * as the windows can be rotated only by 90 degrees. 
+						 * For ghost to be compatible with arbitrary-angle
+						 * rotation, it should be drawn as four lines adjusted
+						 * by the transformation matrix. That would however
+						 * require to equip libdraw with line drawing functionality. */
+
+						transform_t transform = ptr->ghost.transform;
+						double_point_t pos;
+						pos.x = vp->pos.x;
+						pos.y = vp->pos.y;
+						transform_translate(&transform, -pos.x, -pos.y);
+
+						pixel_t ghost_color;
+
+						if (y_bnd_ghost == y_dmg_ghost) {
+							for (sysarg_t x = x_dmg_ghost - vp->pos.x;
+								    x < x_dmg_ghost - vp->pos.x + w_dmg_ghost; ++x) {
+								ghost_color = surface_get_pixel(vp->surface,
+								    x, y_dmg_ghost - vp->pos.y);
+								surface_put_pixel(vp->surface,
+								    x, y_dmg_ghost - vp->pos.y, INVERT(ghost_color));
+							}
+						}
+
+						if (y_bnd_ghost + h_bnd_ghost == y_dmg_ghost + h_dmg_ghost) {
+							for (sysarg_t x = x_dmg_ghost - vp->pos.x;
+								    x < x_dmg_ghost - vp->pos.x + w_dmg_ghost; ++x) {
+								ghost_color = surface_get_pixel(vp->surface,
+								    x, y_dmg_ghost - vp->pos.y + h_dmg_ghost - 1);
+								surface_put_pixel(vp->surface,
+								    x, y_dmg_ghost - vp->pos.y + h_dmg_ghost - 1, INVERT(ghost_color));
+							}
+						}
+
+						if (x_bnd_ghost == x_dmg_ghost) {
+							for (sysarg_t y = y_dmg_ghost - vp->pos.y;
+								    y < y_dmg_ghost - vp->pos.y + h_dmg_ghost; ++y) {
+								ghost_color = surface_get_pixel(vp->surface,
+								    x_dmg_ghost - vp->pos.x, y);
+								surface_put_pixel(vp->surface,
+								    x_dmg_ghost - vp->pos.x, y, INVERT(ghost_color));
+							}
+						}
+
+						if (x_bnd_ghost + w_bnd_ghost == x_dmg_ghost + w_dmg_ghost) {
+							for (sysarg_t y = y_dmg_ghost - vp->pos.y;
+								    y < y_dmg_ghost - vp->pos.y + h_dmg_ghost; ++y) {
+								ghost_color = surface_get_pixel(vp->surface,
+								    x_dmg_ghost - vp->pos.x + w_dmg_ghost - 1, y);
+								surface_put_pixel(vp->surface,
+								    x_dmg_ghost - vp->pos.x + w_dmg_ghost - 1, y, INVERT(ghost_color));
+							}
+						}
+					}
+
+				}
+			}
+
+			list_foreach(pointer_list, link) {
+
 				/* Determine what part of the pointer intersects with the
 				 * updated area of the current viewport. */
@@ -376,10 +478,9 @@
 				if (isec_ptr) {
 					/* Pointer is currently painted directly by copying pixels.
-					 * However, it is possible to draw the painter similarly
+					 * However, it is possible to draw the pointer similarly
 					 * as window by using drawctx_transfer. It would allow
 					 * more sophisticated control over drawing, but would also
 					 * cost more regarding the performance. */
 
-					pixel_t pix = 0;
 					sysarg_t x_vp = x_dmg_ptr - vp->pos.x;
 					sysarg_t y_vp = y_dmg_ptr - vp->pos.y;
@@ -388,12 +489,17 @@
 
 					for (sysarg_t y = 0; y < h_dmg_ptr; ++y) {
-						for (sysarg_t x = 0; x < w_dmg_ptr; ++x) {
-							pix = surface_get_pixel(sf_ptr, x_ptr + x, y_ptr + y);
-							if (ALPHA(pix) == 255) {
-								surface_put_pixel(vp->surface, x_vp + x, y_vp + y, pix);
-							}
+						pixel_t *src = pixelmap_pixel_at(
+						    surface_pixmap_access(sf_ptr), x_ptr, y_ptr + y);
+						pixel_t *dst = pixelmap_pixel_at(
+						    surface_pixmap_access(vp->surface), x_vp, y_vp + y);
+						sysarg_t count = w_dmg_ptr;
+						while (count-- != 0) {
+							*dst = (*src & 0xff000000) ? *src : *dst;
+							++dst; ++src;
 						}
 					}
+					surface_add_damaged_region(vp->surface, x_vp, y_vp, w_dmg_ptr, h_dmg_ptr);
 				}
+
 			}
 		}
@@ -450,5 +556,5 @@
 	} else {
 		fibril_mutex_lock(&window_list_mtx);
-		comp_coord_bounding_rect(x, y, width, height,
+		comp_coord_bounding_rect(x - 1, y - 1, width + 2, height + 2,
 		    win->transform, &x, &y, &width, &height);
 		fibril_mutex_unlock(&window_list_mtx);
@@ -468,5 +574,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;
@@ -541,4 +647,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)
 {
@@ -546,5 +680,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. */
@@ -601,5 +745,5 @@
 			fibril_mutex_lock(&window_list_mtx);
 
-			window_t *win = window_create();
+			window_t *win = window_create(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
 			if (!win) {
 				async_answer_2(callid, ENOMEM, 0, 0);
@@ -630,8 +774,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 {
@@ -953,16 +1109,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)
 {
@@ -973,9 +1117,13 @@
 	transform_t scale;
 	transform_identity(&scale);
-	transform_scale(&scale, win->fx, win->fy);
+	if (win->fx != 1 || win->fy != 1) {
+		transform_scale(&scale, win->fx, win->fy);
+	}
 
 	transform_t rotate;
 	transform_identity(&rotate);
-	transform_rotate(&rotate, win->angle);
+	if (win->angle != 0) {
+		transform_rotate(&rotate, win->angle);
+	}
 
 	transform_t transform;
@@ -994,7 +1142,8 @@
 
 static void comp_window_animate(pointer_t *pointer, window_t *win,
-     sysarg_t *dmg_x, sysarg_t *dmg_y, sysarg_t *dmg_width, sysarg_t *dmg_height)
+    sysarg_t *dmg_x, sysarg_t *dmg_y, sysarg_t *dmg_width, sysarg_t *dmg_height)
 {
 	/* window_list_mtx locked by caller */
+	/* pointer_list_mtx locked by caller */
 
 	int dx = pointer->accum.x;
@@ -1020,5 +1169,5 @@
 		}
 
-		if (scale || resize) {
+		if ((scale || resize) && (win->angle != 0)) {
 			transform_t rotate;
 			transform_identity(&rotate);
@@ -1037,15 +1186,22 @@
 		double _dx = dx;
 		double _dy = dy;
-		transform_t unrotate;
-		transform_identity(&unrotate);
-		transform_rotate(&unrotate, -win->angle);
-		transform_apply_linear(&unrotate, &_dx, &_dy);
+		if (win->angle != 0) {
+			transform_t unrotate;
+			transform_identity(&unrotate);
+			transform_rotate(&unrotate, -win->angle);
+			transform_apply_linear(&unrotate, &_dx, &_dy);
+		}
 		_dx = (pointer->grab_flags & GF_MOVE_X) ? -_dx : _dx;
 		_dy = (pointer->grab_flags & GF_MOVE_Y) ? -_dy : _dy;
 
 		if ((pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_RESIZE_X)) {
-			double fx = 1.0 + (_dx / (width * win->fx));
+			double fx = 1.0 + (_dx / ((width - 1) * win->fx));
 			if (fx > 0) {
+#if ANIMATE_WINDOW_TRANSFORMS == 0
+				if (scale) win->fx *= fx;
+#endif
+#if ANIMATE_WINDOW_TRANSFORMS == 1
 				win->fx *= fx;
+#endif
 				scale_back_x *= fx;
 			}
@@ -1053,7 +1209,12 @@
 
 		if ((pointer->grab_flags & GF_SCALE_Y) || (pointer->grab_flags & GF_RESIZE_Y)) {
-			double fy = 1.0 + (_dy / (height * win->fy));
+			double fy = 1.0 + (_dy / ((height - 1) * win->fy));
 			if (fy > 0) {
+#if ANIMATE_WINDOW_TRANSFORMS == 0
+				if (scale) win->fy *= fy;
+#endif
+#if ANIMATE_WINDOW_TRANSFORMS == 1
 				win->fy *= fy;
+#endif
 				scale_back_y *= fy;
 			}
@@ -1071,4 +1232,113 @@
 	    dmg_x, dmg_y, dmg_width, dmg_height);
 }
+
+#if ANIMATE_WINDOW_TRANSFORMS == 0
+static void comp_ghost_animate(pointer_t *pointer,
+    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;
+	pointer->accum_ghost.x = 0;
+	pointer->accum_ghost.y = 0;
+
+	bool move = (pointer->grab_flags & GF_MOVE_X) || (pointer->grab_flags & GF_MOVE_Y);
+	bool scale = (pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_SCALE_Y);
+	bool resize = (pointer->grab_flags & GF_RESIZE_X) || (pointer->grab_flags & GF_RESIZE_Y);
+
+	sysarg_t width, height;
+	surface_get_resolution(pointer->ghost.surface, &width, &height);
+
+	if (move) {
+		double cx = 0;
+		double cy = 0;
+		if (pointer->grab_flags & GF_MOVE_X) {
+			cx = 1;
+		}
+		if (pointer->grab_flags & GF_MOVE_Y) {
+			cy = 1;
+		}
+
+		if (scale || resize) {
+			transform_t rotate;
+			transform_identity(&rotate);
+			transform_rotate(&rotate, pointer->ghost.angle);
+			transform_apply_linear(&rotate, &cx, &cy);
+		}
+
+		cx = (cx < 0) ? (-1 * cx) : cx;
+		cy = (cy < 0) ? (-1 * cy) : cy;
+
+		pointer->ghost.dx += (cx * dx);
+		pointer->ghost.dy += (cy * dy);
+	}
+
+	if (scale || resize) {
+		double _dx = dx;
+		double _dy = dy;
+		transform_t unrotate;
+		transform_identity(&unrotate);
+		transform_rotate(&unrotate, -pointer->ghost.angle);
+		transform_apply_linear(&unrotate, &_dx, &_dy);
+		_dx = (pointer->grab_flags & GF_MOVE_X) ? -_dx : _dx;
+		_dy = (pointer->grab_flags & GF_MOVE_Y) ? -_dy : _dy;
+
+		if ((pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_RESIZE_X)) {
+			double fx = 1.0 + (_dx / ((width - 1) * pointer->ghost.fx));
+			pointer->ghost.fx *= fx;
+		}
+
+		if ((pointer->grab_flags & GF_SCALE_Y) || (pointer->grab_flags & GF_RESIZE_Y)) {
+			double fy = 1.0 + (_dy / ((height - 1) * pointer->ghost.fy));
+			pointer->ghost.fy *= fy;
+		}
+	}
+
+	sysarg_t x1, y1, width1, height1;
+	sysarg_t x2, y2, width2, height2;
+	comp_coord_bounding_rect(0, 0, width, height, pointer->ghost.transform,
+	    &x1, &y1, &width1, &height1);
+	comp_recalc_transform(&pointer->ghost);
+	comp_coord_bounding_rect(0, 0, width, height, pointer->ghost.transform,
+	    &x2, &y2, &width2, &height2);
+
+	sysarg_t x_u, y_u, w_u, h_u;
+	rectangle_union(x1, y1, width1, height1, x2, y2, width2, height2,
+	    &x_u, &y_u, &w_u, &h_u);
+
+	sysarg_t x_i, y_i, w_i, h_i;
+	rectangle_intersect(x1, y1, width1, height1, x2, y2, width2, height2,
+	    &x_i, &y_i, &w_i, &h_i);
+
+	if (w_i == 0 || h_i == 0) {
+		rect1->x = x_u; rect2->x = 0; rect3->x = 0; rect4->x = 0;
+		rect1->y = y_u; rect2->y = 0; rect3->y = 0; rect4->y = 0;
+		rect1->w = w_u; rect2->w = 0; rect3->w = 0; rect4->w = 0;
+		rect1->h = h_u; rect2->h = 0; rect3->h = 0; rect4->h = 0;
+	} else {
+		rect1->x = x_u;
+		rect1->y = y_u;
+		rect1->w = x_i - x_u + 1;
+		rect1->h = h_u;
+
+		rect2->x = x_u;
+		rect2->y = y_u;
+		rect2->w = w_u;
+		rect2->h = y_i - y_u + 1;
+
+		rect3->x = x_i + w_i - 1;
+		rect3->y = y_u;
+		rect3->w = w_u - w_i - x_i + x_u + 1;
+		rect3->h = h_u;
+		
+		rect4->x = x_u;
+		rect4->y = y_i + h_i - 1;
+		rect4->w = w_u;
+		rect4->h = h_u - h_i - y_i + y_u + 1;
+	}
+}
+#endif
 
 static int comp_abs_move(input_t *input, unsigned x , unsigned y,
@@ -1125,4 +1395,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) {
@@ -1136,8 +1407,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);
@@ -1148,16 +1419,45 @@
 					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. */
 			pointer->accum.x += dx;
 			pointer->accum.y += dy;
+			pointer->accum_ghost.x += dx;
+			pointer->accum_ghost.y += dy;
+#if ANIMATE_WINDOW_TRANSFORMS == 0
+			if (pointer->ghost.surface == NULL) {
+				pointer->ghost.surface = top->surface;
+				pointer->ghost.dx = top->dx;
+				pointer->ghost.dy = top->dy;
+				pointer->ghost.fx = top->fx;
+				pointer->ghost.fy = top->fy;
+				pointer->ghost.angle = top->angle;
+				pointer->ghost.transform = top->transform;
+			}
+			desktop_rect_t dmg_rect1, dmg_rect2, dmg_rect3, dmg_rect4;
+			comp_ghost_animate(pointer, &dmg_rect1, &dmg_rect2, &dmg_rect3, &dmg_rect4);
+#endif
 #if ANIMATE_WINDOW_TRANSFORMS == 1
 			sysarg_t x, y, width, height;
 			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
+			comp_damage(dmg_rect1.x, dmg_rect1.y, dmg_rect1.w, dmg_rect1.h);
+			comp_damage(dmg_rect2.x, dmg_rect2.y, dmg_rect2.w, dmg_rect2.h);
+			comp_damage(dmg_rect3.x, dmg_rect3.y, dmg_rect3.w, dmg_rect3.h);
+			comp_damage(dmg_rect4.x, dmg_rect4.y, dmg_rect4.w, dmg_rect4.h);
+#endif
 #if ANIMATE_WINDOW_TRANSFORMS == 1
 			comp_damage(x, y, width, height);
@@ -1165,4 +1465,5 @@
 		}
 	} else {
+		fibril_mutex_unlock(&pointer_list_mtx);
 		fibril_mutex_unlock(&window_list_mtx);
 	}
@@ -1174,4 +1475,44 @@
 {
 	pointer_t *pointer = input_pointer(input);
+
+	fibril_mutex_lock(&window_list_mtx);
+	fibril_mutex_lock(&pointer_list_mtx);
+	window_t *win = NULL;
+	sysarg_t point_x = 0;
+	sysarg_t point_y = 0;
+	sysarg_t width, height;
+	bool within_client = false;
+
+	/* Determine the window which the mouse click belongs to. */
+	list_foreach(window_list, link) {
+		win = list_get_instance(link, window_t, link);
+		if (win->surface) {
+			surface_get_resolution(win->surface, &width, &height);
+			within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
+			    win->transform, width, height, &point_x, &point_y);
+		}
+		if (within_client) {
+			break;
+		}
+	}
+
+	/* Check whether the window is top-level window. */
+	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_top = NULL;
+	window_event_t *event_unfocus = NULL;
+	window_t *win_unfocus = NULL;
+	sysarg_t dmg_x, dmg_y;
+	sysarg_t dmg_width = 0;
+	sysarg_t dmg_height = 0;
+	
+#if ANIMATE_WINDOW_TRANSFORMS == 0
+	desktop_rect_t dmg_rect1, dmg_rect2, dmg_rect3, dmg_rect4;
+#endif
 
 	if (bpress) {
@@ -1180,69 +1521,37 @@
 		pointer->pressed = true;
 
-		/* Check whether mouse press belongs to the top-level window. */
-		fibril_mutex_lock(&window_list_mtx);
-		window_t *win = (window_t *) list_first(&window_list);
-		if (!win || !win->surface) {
-			fibril_mutex_unlock(&window_list_mtx);
-			return EOK;
-		}
-		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,
-		    win->transform, width, height, &x, &y);
-		fibril_mutex_unlock(&window_list_mtx);
-
-		/* Send mouse press to the top-level window. */
+		/* 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);
+		}
+
+		/* Notify top-level window about mouse press. */
 		if (within_client) {
-			window_event_t *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 = x;
-				event->data.pos.vpos = y;
-				comp_post_event(event);
-			} else {
-				return ENOMEM;
-			}
-		}
+			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;
+		}
+
 	} else if (pointer->pressed && pointer->btn_num == (unsigned)bnum) {
 		pointer->pressed = false;
 
-		fibril_mutex_lock(&window_list_mtx);
-		window_t *win = NULL;
-		sysarg_t point_x = 0;
-		sysarg_t point_y = 0;
-		sysarg_t width, height;
-		bool within_client = false;
-
-		/* Determine the window which the mouse release belongs to. */
-		list_foreach(window_list, link) {
-			win = list_get_instance(link, window_t, link);
-			if (win->surface) {
-				surface_get_resolution(win->surface, &width, &height);
-				within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
-				    win->transform, width, height, &point_x, &point_y);
-			}
-			if (within_client) {
-				break;
-			}
-		}
-
-		/* Check whether the window is top-level window. */
-		window_t *top = (window_t *) list_first(&window_list);
-		if (!win || !top) {
-			pointer->grab_flags = GF_EMPTY;
-			fibril_mutex_unlock(&window_list_mtx);
-			return EOK;
-		}
-
-		window_event_t *event = NULL;
-		sysarg_t dmg_x, dmg_y;
-		sysarg_t dmg_width = 0;
-		sysarg_t dmg_height = 0;
-
+#if ANIMATE_WINDOW_TRANSFORMS == 0
 		sysarg_t pre_x = 0; 
 		sysarg_t pre_y = 0;
@@ -1250,6 +1559,9 @@
 		sysarg_t pre_height = 0;
 
-#if ANIMATE_WINDOW_TRANSFORMS == 0
 		if (pointer->grab_flags != GF_EMPTY) {
+			if (pointer->ghost.surface) {
+				comp_ghost_animate(pointer, &dmg_rect1, &dmg_rect2, &dmg_rect3, &dmg_rect4);
+				pointer->ghost.surface = NULL;
+			}
 			comp_window_animate(pointer, top, &pre_x, &pre_y, &pre_width, &pre_height);
 			dmg_x = pre_x;
@@ -1263,13 +1575,15 @@
 
 			surface_get_resolution(top->surface, &width, &height);
+#if ANIMATE_WINDOW_TRANSFORMS == 1
 			top->fx *= (1.0 / scale_back_x);
 			top->fy *= (1.0 / scale_back_y);
 			comp_recalc_transform(top);
+#endif
 
 			/* 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));
@@ -1277,15 +1591,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;
 				}
 			}
@@ -1296,23 +1610,15 @@
 			
 			/* 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;
-			
-		} else if (within_client && (pointer->grab_flags == GF_EMPTY) && (bnum == 1)) {
-
-			/* Bring the window to the foreground. */
-			list_remove(&win->link);
-			list_prepend(&win->link, &window_list);
-			comp_coord_bounding_rect(0, 0, width, height, win->transform,
-			    &dmg_x, &dmg_y, &dmg_width, &dmg_height);
 			
 		} else {
@@ -1320,13 +1626,26 @@
 		}
 
-		fibril_mutex_unlock(&window_list_mtx);
-
-		if (dmg_width > 0 && dmg_height > 0) {
-			comp_damage(dmg_x, dmg_y, dmg_width, dmg_height);
-		}
-
-		if (event) {
-			comp_post_event(event);
-		}
+	}
+
+	fibril_mutex_unlock(&pointer_list_mtx);
+	fibril_mutex_unlock(&window_list_mtx);
+
+#if ANIMATE_WINDOW_TRANSFORMS == 0
+		comp_damage(dmg_rect1.x, dmg_rect1.y, dmg_rect1.w, dmg_rect1.h);
+		comp_damage(dmg_rect2.x, dmg_rect2.y, dmg_rect2.w, dmg_rect2.h);
+		comp_damage(dmg_rect3.x, dmg_rect3.y, dmg_rect3.w, dmg_rect3.h);
+		comp_damage(dmg_rect4.x, dmg_rect4.y, dmg_rect4.w, dmg_rect4.h);
+#endif
+
+	if (dmg_width > 0 && dmg_height > 0) {
+		comp_damage(dmg_x, dmg_y, dmg_width, dmg_height);
+	}
+
+	if (event_unfocus && win_unfocus) {
+		comp_post_event_win(event_unfocus, win_unfocus);
+	}
+
+	if (event_top) {
+		comp_post_event_top(event_top);
 	}
 
@@ -1452,5 +1771,5 @@
 
 			fibril_mutex_unlock(&window_list_mtx);
-			comp_post_event(event);
+			comp_post_event_top(event);
 		} else {
 			fibril_mutex_unlock(&window_list_mtx);
@@ -1494,5 +1813,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);
@@ -1502,4 +1821,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;
@@ -1530,4 +1861,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 {
@@ -1600,5 +1940,5 @@
 		fibril_mutex_lock(&window_list_mtx);
 
-		window_t *red_win = window_create();
+		window_t *red_win = window_create(0, 0);
 		red_win->surface = surface_create(250, 150, NULL, 0);
 		pixel_t red_pix = PIXEL(255, 240, 0, 0);
@@ -1610,5 +1950,5 @@
 		list_prepend(&red_win->link, &window_list);
 
-		window_t *blue_win = window_create();
+		window_t *blue_win = window_create(0, 0);
 		blue_win->surface = surface_create(200, 100, NULL, 0);
 		pixel_t blue_pix = PIXEL(255, 0, 0, 240);
@@ -1620,9 +1960,9 @@
 		list_prepend(&blue_win->link, &window_list);
 
-		window_t *helenos_win = window_create();
+		window_t *helenos_win = window_create(0, 0);
 		helenos_win->surface = decode_tga((void *) helenos_tga, helenos_tga_size, 0);
 		list_prepend(&helenos_win->link, &window_list);
 
-		window_t *nameic_win = window_create();
+		window_t *nameic_win = window_create(0, 0);
 		nameic_win->surface = decode_tga((void *) nameic_tga, nameic_tga_size, 0);
 		list_prepend(&nameic_win->link, &window_list);
@@ -1642,5 +1982,5 @@
 		event->data.kbd.c = c;
 
-		comp_post_event(event);
+		comp_post_event_top(event);
 	}
 
@@ -1693,5 +2033,5 @@
 static void input_disconnect(void)
 {
-    	pointer_t *pointer = input->user;
+	pointer_t *pointer = input->user;
 	input_close(input);
 	pointer_destroy(pointer);
@@ -1706,5 +2046,5 @@
 {
 	/* Coordinates of the central pixel. */
-	coord_origin = UINT32_MAX / 2;
+	coord_origin = UINT32_MAX / 4;
 	
 	/* Color of the viewport background. Must be opaque. */
Index: uspace/srv/hid/compositor/compositor.h
===================================================================
--- uspace/srv/hid/compositor/compositor.h	(revision ce60be1a85249a003137d846c99ab01a330a0439)
+++ uspace/srv/hid/compositor/compositor.h	(revision 69c1995350adfe31ce9f6f2a6810575aa43f26bf)
@@ -43,4 +43,11 @@
 typedef desktop_point_t desktop_vector_t;
 
+typedef struct {
+	desktop_coord_t x;
+	desktop_coord_t y;
+	desktop_coord_t w;
+	desktop_coord_t h;
+} desktop_rect_t;
+
 /* TODO remove? */
 typedef struct {
