agl-shell.xml: Introduce a new interface
[src/agl-compositor.git] / src / shell.c
index cb6e592..4211399 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2019 Collabora, Ltd.
+ * Copyright © 2019, 2022 Collabora, Ltd.
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -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>
@@ -928,6 +929,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)
 {
@@ -1394,6 +1426,22 @@ shell_destroy(struct wl_client *client, struct wl_resource *res)
 {
 }
 
+static void
+shell_ext_destroy(struct wl_client *client, struct wl_resource *res)
+{
+       wl_resource_destroy(res);
+}
+
+static void
+shell_ext_doas(struct wl_client *client, struct wl_resource *res)
+{
+       struct  ivi_compositor *ivi = wl_resource_get_user_data(res);
+
+       ivi->shell_client_ext.doas_requested = true;
+       agl_shell_ext_send_doas_done(ivi->shell_client_ext.resource,
+                                    AGL_SHELL_EXT_DOAS_SHELL_CLIENT_STATUS_SUCCESS);
+}
+
 static const struct agl_shell_interface agl_shell_implementation = {
        .destroy = shell_destroy,
        .ready = shell_ready,
@@ -1402,6 +1450,11 @@ static const struct agl_shell_interface agl_shell_implementation = {
        .activate_app = shell_activate_app,
 };
 
+static const struct agl_shell_ext_interface agl_shell_ext_implementation = {
+       .destroy = shell_ext_destroy,
+       .doas_shell_client = shell_ext_doas,
+};
+
 static void
 shell_desktop_set_app_property(struct wl_client *client,
                               struct wl_resource *shell_res,
@@ -1527,6 +1580,14 @@ unbind_agl_shell(struct wl_resource *resource)
        ivi->shell_client.client = NULL;
 }
 
+static void
+unbind_agl_shell_ext(struct wl_resource *resource)
+{
+       struct ivi_compositor *ivi = wl_resource_get_user_data(resource);
+
+       ivi->shell_client_ext.resource = NULL;
+}
+
 static void
 bind_agl_shell(struct wl_client *client,
               void *data, uint32_t version, uint32_t id)
@@ -1558,8 +1619,25 @@ bind_agl_shell(struct wl_client *client,
                        return;
                }
 
-               agl_shell_send_bound_fail(resource);
-               ivi->shell_client.status = BOUND_FAILED;
+               if (ivi->shell_client_ext.resource && 
+                   ivi->shell_client_ext.doas_requested) {
+
+                       wl_resource_set_implementation(resource, &agl_shell_implementation,
+                                                      ivi, NULL);
+                       ivi->shell_client_ext.resource = resource;
+
+                       if (ivi->shell_client.status == BOUND_OK &&
+                           wl_resource_get_version(resource) >= AGL_SHELL_BOUND_OK_SINCE_VERSION) {
+                               weston_log("Sent agl_shell_send_bound_ok to client ext\n");
+                               ivi->shell_client_ext.status = BOUND_OK;
+                               agl_shell_send_bound_ok(ivi->shell_client_ext.resource);
+                       }
+
+                       return;
+               } else {
+                       agl_shell_send_bound_fail(resource);
+                       ivi->shell_client.status = BOUND_FAILED;
+               }
        }
 
        wl_resource_set_implementation(resource, &agl_shell_implementation,
@@ -1571,6 +1649,30 @@ bind_agl_shell(struct wl_client *client,
                agl_shell_send_bound_ok(ivi->shell_client.resource);
 }
 
+static void
+bind_agl_shell_ext(struct wl_client *client,
+                  void *data, uint32_t version, uint32_t id)
+{
+       struct ivi_compositor *ivi = data;
+       struct wl_resource *resource;
+
+       resource = wl_resource_create(client, &agl_shell_ext_interface, version, id);
+       if (!resource) {
+               wl_client_post_no_memory(client);
+               return;
+       }
+
+       if (ivi->shell_client_ext.resource) {
+               wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+                                      "agl_shell_ext has already been bound");
+               return;
+       }
+
+       wl_resource_set_implementation(resource, &agl_shell_ext_implementation,
+                                      ivi, unbind_agl_shell_ext);
+       ivi->shell_client_ext.resource = resource;
+}
+
 static void
 unbind_agl_shell_desktop(struct wl_resource *resource)
 {
@@ -1634,6 +1736,14 @@ ivi_shell_create_global(struct ivi_compositor *ivi)
                return -1;
        }
 
+       ivi->agl_shell_ext = wl_global_create(ivi->compositor->wl_display,
+                                             &agl_shell_ext_interface, 1,
+                                             ivi, bind_agl_shell_ext);
+       if (!ivi->agl_shell_ext) {
+               weston_log("Failed to create agl_shell_ext global.\n");
+               return -1;
+       }
+
        ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
                                                  &agl_shell_desktop_interface, 2,
                                                  ivi, bind_agl_shell_desktop);