compositor: Handle output destruction deferral
[src/agl-compositor.git] / src / shell.c
index cb6e592..cefd157 100644 (file)
@@ -33,6 +33,7 @@
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <unistd.h>
 #include <libweston/libweston.h>
 #include <libweston/config-parser.h>
@@ -90,6 +91,16 @@ ivi_set_desktop_surface(struct ivi_surface *surface)
        agl_shell_desktop_advertise_application_id(ivi, surface);
 }
 
+static void
+ivi_set_background_surface(struct ivi_surface *surface)
+{
+       struct ivi_compositor *ivi = surface->ivi;
+       assert(surface->role == IVI_SURFACE_ROLE_BACKGROUND);
+
+       wl_list_insert(&surface->ivi->surfaces, &surface->link);
+       agl_shell_desktop_advertise_application_id(ivi, surface);
+}
+
 static void
 ivi_set_desktop_surface_popup(struct ivi_surface *surface)
 {
@@ -928,6 +939,37 @@ struct process_info {
        char *path;
 };
 
+int
+sigchld_handler(int signal_number, void *data)
+{
+       struct weston_process *p;
+       struct ivi_compositor *ivi = data;
+       int status;
+       pid_t pid;
+
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+               wl_list_for_each(p, &ivi->child_process_list, link) {
+                       if (p->pid == pid)
+                               break;
+               }
+
+               if (&p->link == &ivi->child_process_list) {
+                       weston_log("unknown child process exited\n");
+                       continue;
+               }
+
+               wl_list_remove(&p->link);
+               wl_list_init(&p->link);
+               p->cleanup(p, status);
+       }
+
+       if (pid < 0 && errno != ECHILD)
+               weston_log("waitpid error %s\n", strerror(errno));
+
+       return 1;
+}
+
+
 static void
 process_handle_sigchld(struct weston_process *process, int status)
 {
@@ -1132,8 +1174,14 @@ shell_ready(struct wl_client *client, struct wl_resource *shell_res)
        ivi->shell_client.ready = true;
 
        wl_list_for_each(output, &ivi->outputs, link) {
-               if (output->background)
+               if (output->background &&
+                   output->background->role == IVI_SURFACE_ROLE_BACKGROUND) {
+                       /* track the background surface role as a "regular"
+                        * surface so we can activate it */
+                       ivi_set_background_surface(output->background);
                        remove_black_curtain(output);
+               }
+
                ivi_layout_init(ivi, output);
        }
 
@@ -1394,12 +1442,33 @@ shell_destroy(struct wl_client *client, struct wl_resource *res)
 {
 }
 
+static void
+shell_set_activate_region(struct wl_client *client, struct wl_resource *res,
+                         struct wl_resource *output, int x, int y,
+                         int width, int height)
+{
+       struct ivi_compositor *ivi = wl_resource_get_user_data(res);
+       struct weston_head *head = weston_head_from_resource(output);
+       struct weston_output *woutput = weston_head_get_output(head);
+       struct ivi_output *ioutput = to_ivi_output(woutput);
+
+       struct weston_geometry area = { .x = x, .y = y,
+                                       .width = width,
+                                       .height = height };
+       if (ivi->shell_client.ready)
+               return;
+
+       ioutput->area_activation = area;
+}
+
+
 static const struct agl_shell_interface agl_shell_implementation = {
-       .destroy = shell_destroy,
        .ready = shell_ready,
        .set_background = shell_set_background,
        .set_panel = shell_set_panel,
        .activate_app = shell_activate_app,
+       .destroy = shell_destroy,
+       .set_activate_region = shell_set_activate_region
 };
 
 static void
@@ -1627,7 +1696,7 @@ int
 ivi_shell_create_global(struct ivi_compositor *ivi)
 {
        ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
-                                         &agl_shell_interface, 3,
+                                         &agl_shell_interface, 4,
                                          ivi, bind_agl_shell);
        if (!ivi->agl_shell) {
                weston_log("Failed to create wayland global.\n");