compositor: Handle disappearing surfaces and input devices for touch
diff --git a/compositor/compositor.c b/compositor/compositor.c
index 737bd34..0fa9ed8 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -1455,6 +1455,28 @@
 }
 
 static void
+lose_touch_focus_resource(struct wl_listener *listener,
+			  struct wl_resource *resource, uint32_t time)
+{
+	struct wlsc_input_device *device =
+		container_of(listener, struct wlsc_input_device,
+			     touch_focus_resource_listener);
+
+	device->touch_focus_resource = NULL;
+}
+
+static void
+lose_touch_focus(struct wl_listener *listener,
+		 struct wl_resource *resource, uint32_t time)
+{
+	struct wlsc_input_device *device =
+		container_of(listener, struct wlsc_input_device,
+			     touch_focus_listener);
+
+	device->touch_focus = NULL;
+}
+
+static void
 touch_set_focus(struct wlsc_input_device *device,
 		struct wl_surface *surface, uint32_t time)
 {
@@ -1464,15 +1486,33 @@
 	if (device->touch_focus == surface)
 		return;
 
-	resource = find_resource_for_surface(&input_device->resource_list,
-					     surface);
-	if (!resource) {
-		fprintf(stderr, "couldn't find resource\n");
-		return;
-	}
+	if (surface) {
+		resource =
+			find_resource_for_surface(&input_device->resource_list,
+						  surface);
+		if (!resource) {
+			fprintf(stderr, "couldn't find resource\n");
+			return;
+		}
 
-	device->touch_focus = surface;
-	device->touch_focus_resource = resource;
+		device->touch_focus_resource_listener.func =
+			lose_touch_focus_resource;
+		wl_list_insert(resource->destroy_listener_list.prev,
+			       &device->touch_focus_resource_listener.link);
+		device->touch_focus_listener.func = lose_touch_focus;
+		wl_list_insert(surface->resource.destroy_listener_list.prev,
+			       &device->touch_focus_listener.link);
+
+		device->touch_focus = surface;
+		device->touch_focus_resource = resource;
+	} else {
+		if (device->touch_focus)
+			wl_list_remove(&device->touch_focus_listener.link);
+		if (device->touch_focus_resource)
+			wl_list_remove(&device->touch_focus_resource_listener.link);
+		device->touch_focus = NULL;
+		device->touch_focus_resource = NULL;
+	}
 }
 
 /**
@@ -1504,11 +1544,12 @@
 		if (wd->num_tp == 1) {
 			es = wlsc_compositor_pick_surface(ec, x, y, &sx, &sy);
 			touch_set_focus(wd, &es->surface, time);
-		} else {
+		} else if (wd->touch_focus) {
 			es = (struct wlsc_surface *) wd->touch_focus;
 			wlsc_surface_transform(es, x, y, &sx, &sy);
 		}
-		if (wd->touch_focus_resource)
+
+		if (wd->touch_focus_resource && wd->touch_focus)
 			wl_resource_post_event(wd->touch_focus_resource,
 					       touch_type, time,
 					       wd->touch_focus,
@@ -1516,6 +1557,9 @@
 		break;
 	case WL_INPUT_DEVICE_TOUCH_MOTION:
 		es = (struct wlsc_surface *) wd->touch_focus;
+		if (!es)
+			break;
+
 		wlsc_surface_transform(es, x, y, &sx, &sy);
 		if (wd->touch_focus_resource)
 			wl_resource_post_event(wd->touch_focus_resource,
@@ -1529,10 +1573,8 @@
 		if (wd->touch_focus_resource)
 			wl_resource_post_event(wd->touch_focus_resource,
 					       touch_type, time, touch_id);
-		if (wd->num_tp == 0) {
-			wd->touch_focus = NULL;
-			wd->touch_focus_resource = NULL;
-		}
+		if (wd->num_tp == 0)
+			touch_set_focus(wd, NULL, time);
 		break;
 	}
 }
diff --git a/compositor/compositor.h b/compositor/compositor.h
index 0501cca..2b1e56d 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -117,7 +117,9 @@
 
 	uint32_t num_tp;
 	struct wl_surface *touch_focus;
+	struct wl_listener touch_focus_listener;
 	struct wl_resource *touch_focus_resource;
+	struct wl_listener touch_focus_resource_listener;
 };
 
 enum wlsc_visual {