Send surface enter/leave events

These new protocol events allow us to tell which outputs a surface is on, and
potentially update where we allocate our buffers from.

Signed-off-by: Casey Dahlin <cdahlin@redhat.com>
diff --git a/src/compositor.c b/src/compositor.c
index 17a0cc6..ddbc077 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1138,19 +1138,48 @@
         return NULL;
 }
 
+static void
+weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask)
+{
+	uint32_t different = es->output_mask ^ mask;
+	uint32_t entered = mask & different;
+	uint32_t left = es->output_mask & different;
+	struct weston_output *output;
+	struct wl_resource *resource;
+	struct wl_client *client = es->surface.resource.client;
+
+	if (es->surface.resource.client == NULL)
+		return;
+	if (different == 0)
+		return;
+
+	es->output_mask = mask;
+	wl_list_for_each(output, &es->compositor->output_list, link) {
+		if (1 << output->id & different)
+			resource =
+				find_resource_for_client(&output->resource_list,
+							 client);
+		if (1 << output->id & entered)
+			wl_surface_send_enter(&es->surface.resource, resource);
+		if (1 << output->id & left)
+			wl_surface_send_leave(&es->surface.resource, resource);
+	}
+}
+
 WL_EXPORT void
 weston_surface_assign_output(struct weston_surface *es)
 {
 	struct weston_compositor *ec = es->compositor;
 	struct weston_output *output, *new_output;
 	pixman_region32_t region;
-	uint32_t max, area;
+	uint32_t max, area, mask;
 	pixman_box32_t *e;
 
 	weston_surface_update_transform(es);
 
 	new_output = NULL;
 	max = 0;
+	mask = 0;
 	pixman_region32_init(&region);
 	wl_list_for_each(output, &ec->output_list, link) {
 		pixman_region32_intersect(&region, &es->transform.boundingbox,
@@ -1159,6 +1188,9 @@
 		e = pixman_region32_extents(&region);
 		area = (e->x2 - e->x1) * (e->y2 - e->y1);
 
+		if (area > 0)
+			mask |= 1 << output->id;
+
 		if (area >= max) {
 			new_output = output;
 			max = area;
@@ -1167,6 +1199,8 @@
 	pixman_region32_fini(&region);
 
 	es->output = new_output;
+	weston_surface_update_output_mask(es, mask);
+
 	if (!wl_list_empty(&es->frame_callback_list)) {
 		wl_list_insert_list(new_output->frame_callback_list.prev,
 				    &es->frame_callback_list);
@@ -1962,7 +1996,7 @@
 	device->drag_surface = NULL;
 }
 
-static void unbind_input_device(struct wl_resource *resource)
+static void unbind_resource(struct wl_resource *resource)
 {
 	wl_list_remove(&resource->link);
 	free(resource);
@@ -1978,7 +2012,7 @@
 	resource = wl_client_add_object(client, &wl_input_device_interface,
 					&input_device_interface, id, data);
 	wl_list_insert(&device->resource_list, &resource->link);
-	resource->destroy = unbind_input_device;
+	resource->destroy = unbind_resource;
 }
 
 static void
@@ -2152,6 +2186,9 @@
 	resource = wl_client_add_object(client,
 					&wl_output_interface, NULL, id, data);
 
+	wl_list_insert(&output->resource_list, &resource->link);
+	resource->destroy = unbind_resource;
+
 	wl_output_send_geometry(resource,
 				output->x,
 				output->y,
@@ -2275,6 +2312,7 @@
 
 	pixman_region32_fini(&output->region);
 	pixman_region32_fini(&output->previous_damage);
+	output->compositor->output_id_pool &= ~(1 << output->id);
 
 	wl_display_remove_global(c->wl_display, output->global);
 }
@@ -2364,6 +2402,7 @@
 	weston_output_damage(output);
 
 	wl_list_init(&output->frame_callback_list);
+	wl_list_init(&output->resource_list);
 
 	output->id = ffs(~output->compositor->output_id_pool) - 1;
 	output->compositor->output_id_pool |= 1 << output->id;