window.c: Move window items to window.c
diff --git a/clients/window.c b/clients/window.c
index e7a61ef..9e92adb 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -125,11 +125,22 @@
 	window_motion_handler_t motion_handler;
 	window_enter_handler_t enter_handler;
 	window_leave_handler_t leave_handler;
+	window_item_focus_handler_t item_focus_handler;
+
+	struct wl_list item_list;
+	struct item *focus_item;
+	uint32_t item_grab_button;
 
 	void *user_data;
 	struct wl_list link;
 };
 
+struct item {
+	struct wl_list link;
+	struct rectangle allocation;
+	void *user_data;
+};
+
 struct input {
 	struct display *display;
 	struct wl_input_device *input_device;
@@ -949,6 +960,73 @@
 	free(window);
 }
 
+static struct item *
+window_find_item(struct window *window, int32_t x, int32_t y)
+{
+	struct item *item;
+
+	wl_list_for_each(item, &window->item_list, link) {
+		if (item->allocation.x <= x &&
+		    x < item->allocation.x + item->allocation.width &&
+		    item->allocation.y <= y &&
+		    y < item->allocation.y + item->allocation.height) {
+			return item;
+		}
+	}
+
+	return NULL;
+}
+
+struct item *
+window_add_item(struct window *window, void *data)
+{
+	struct item *item;
+
+	item = malloc(sizeof *item);
+	memset(item, 0, sizeof *item);
+	item->user_data = data;
+	wl_list_insert(window->item_list.prev, &item->link);
+
+	return item;
+}
+
+void
+window_for_each_item(struct window *window, item_func_t func, void *data)
+{
+	struct item *item;
+
+	wl_list_for_each(item, &window->item_list, link)
+		func(item, data);
+}
+
+struct item *
+window_get_focus_item(struct window *window)
+{
+	return window->focus_item;
+}
+
+void
+item_get_allocation(struct item *item, struct rectangle *allocation)
+{
+	*allocation = item->allocation;
+}
+
+void
+item_set_allocation(struct item *item,
+		    int32_t x, int32_t y, int32_t width, int32_t height)
+{
+	item->allocation.x = x;
+	item->allocation.y = y;
+	item->allocation.width = width;
+	item->allocation.height = height;
+}
+
+void *
+item_get_user_data(struct item *item)
+{
+	return item->user_data;
+}
+
 void
 display_flush_cairo_device(struct display *display)
 {
@@ -1079,12 +1157,27 @@
 }
 
 static void
+window_set_focus_item(struct window *window, struct item *focus)
+{
+	void *data;
+
+	if (focus == window->focus_item)
+		return;
+
+	window->focus_item = focus;
+	data = focus ? focus->user_data : NULL;
+	if (window->item_focus_handler)
+		window->item_focus_handler(window, focus, data);
+}
+
+static void
 window_handle_motion(void *data, struct wl_input_device *input_device,
 		     uint32_t time,
 		     int32_t x, int32_t y, int32_t sx, int32_t sy)
 {
 	struct input *input = data;
 	struct window *window = input->pointer_focus;
+	struct item *item;
 	int pointer = POINTER_LEFT_PTR;
 
 	input->x = x;
@@ -1092,6 +1185,11 @@
 	input->sx = sx;
 	input->sy = sy;
 
+	if (!window->focus_item || !window->item_grab_button) {
+		item = window_find_item(window, sx, sy);
+		window_set_focus_item(window, item);
+	}
+
 	if (window->motion_handler)
 		pointer = (*window->motion_handler)(window, input, time,
 						    x, y, sx, sy,
@@ -1107,8 +1205,12 @@
 {
 	struct input *input = data;
 	struct window *window = input->pointer_focus;
+	struct item *item;
 	int location;
 
+	if (window->focus_item && window->item_grab_button == 0 && state)
+		window->item_grab_button = button;
+
 	location = get_pointer_location(window, input->sx, input->sy);
 
 	if (button == BTN_LEFT && state == 1) {
@@ -1144,6 +1246,13 @@
 						  button, state,
 						  window->user_data);
 	}
+
+	if (window->focus_item &&
+	    window->item_grab_button == button && !state) {
+		window->item_grab_button = 0;
+		item = window_find_item(window, input->sx, input->sy);
+		window_set_focus_item(window, item);
+	}
 }
 
 static void
@@ -1184,10 +1293,13 @@
 {
 	struct input *input = data;
 	struct window *window;
+	struct item *item;
 	int pointer;
 
 	window = input->pointer_focus;
 	if (window && window->surface != surface) {
+		window_set_focus_item(window, NULL);
+
 		if (window->leave_handler)
 			window->leave_handler(window, input,
 					      time, window->user_data);
@@ -1210,8 +1322,10 @@
 							time, sx, sy,
 							window->user_data);
 
-		set_pointer_image(input, time, pointer);
+		item = window_find_item(window, x, y);
+		window_set_focus_item(window, item);
 
+		set_pointer_image(input, time, pointer);
 	}
 }
 
@@ -1504,6 +1618,13 @@
 }
 
 void
+window_set_item_focus_handler(struct window *window,
+			      window_item_focus_handler_t handler)
+{
+	window->item_focus_handler = handler;
+}
+
+void
 window_set_transparent(struct window *window, int transparent)
 {
 	window->transparent = transparent;
@@ -1562,6 +1683,7 @@
 	window->margin = 16;
 	window->decoration = 1;
 	window->transparent = 1;
+	wl_list_init(&window->item_list);
 
 	if (display->dpy)
 #ifdef HAVE_CAIRO_EGL