agl-shell.xml: Introduce a new interface
authorMarius Vlad <marius.vlad@collabora.com>
Sat, 8 Oct 2022 18:06:18 +0000 (21:06 +0300)
committerMarius Vlad <marius.vlad@collabora.com>
Fri, 21 Oct 2022 17:16:50 +0000 (20:16 +0300)
In order to allow another other client bind to agl_shell interface, this
introduces a new specific interface which the client would bind to
first, issue a doas_shell_client request, wait for a response, and
proceeed further if the event received was successful. Afterwards, the
client can bind to agl_shell protocol (and assuming it got 'bound_ok'
event back) can further use the agl_shell protocol as it happens with
the shell client.

This approach avoids adding a new protocol interface and instead re-uses
the same interface, with the note that the shell client is still in
charge of handling background and panels.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Change-Id: Iac1d840a5f917b2a92fdfbdcdc583144d3942a1c

protocol/agl-shell.xml
src/ivi-compositor.h
src/shell.c

index ad5553d..25b6a69 100644 (file)
 
 
   </interface>
+  <interface name="agl_shell_ext" version="1">
+    <description summary="extended user interface for Automotive Grade Linux platform">
+      This interface allows another client bind to the agl_shell interface in
+      case there's another shell client already present.
+
+      The client should first bind to this interface and then inform the
+      compositor with the 'doas_shell_client' request and it wants to bind to
+      the agl_shell interface. The client is still expected if using a new
+      version of the agl_shell interface to wait for the 'bound_ok' and
+      'bound_fail' events before issueing any other requests/events.
+
+      Note that this interface has its limitations, and the compositor would
+      still refuse the act for 'set_panel' or 'set_background' requests
+      of the agl_shell interface if there's already a client that used them. Any
+      other requests or events should be delievered and handled as it would
+      a client bound to the agl_shell interface.
+    </description>
+
+    <enum name="doas_shell_client_status">
+      <entry name="success" value="0"/>
+      <entry name="failed" value="1"/>
+    </enum>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroys the factory object">
+        Call the destructor once you're ready with agl_shell_ext interface.
+        This would reset the state and would make any requests made
+        on the agl_shell interface null. The client would need to bind again
+        the agl_shell_ext and issue a 'doas_shell_client' request.
+      </description>
+    </request>
+
+    <request name="doas_shell_client">
+      <description summary="Informs the compositor it wants to bind to agl_shell interface">
+        Prior to binding  to agl_shell interface, this request would inform
+        the compositor it wants to gain access the agl_shell interface. The
+        client is expected to wait for 'doas_shell_client_done' event and check for
+        a successful status before going further with binding to the agl_shell
+        interface.
+      </description>
+    </request>
+
+    <event name="doas_done">
+      <description summary="event sent as a reply to doas_shell_client">
+         The client should check the status event to verify that the
+         compositor was able to handle the request.
+      </description>
+      <arg name="status" type="uint" enum="doas_shell_client_status"/>
+    </event>
+  </interface>
 </protocol>
index bf96fc7..5a0f66c 100644 (file)
@@ -81,14 +81,24 @@ struct ivi_compositor {
 
        struct wl_global *agl_shell;
        struct wl_global *agl_shell_desktop;
+       struct wl_global *agl_shell_ext;
 
        struct {
                struct wl_client *client;
                struct wl_resource *resource;
+
+               struct wl_client *client_ext;
+               struct wl_resource *resource_ext;
                bool ready;
                enum agl_shell_bound_status status;
        } shell_client;
 
+       struct {
+               struct wl_resource *resource;
+               bool doas_requested;
+               enum agl_shell_bound_status status;
+       } shell_client_ext;
+
        struct wl_list desktop_clients; /* desktop_client::link */
 
        struct wl_list outputs; /* ivi_output.link */
index 96f5c63..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
@@ -1426,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,
@@ -1434,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,
@@ -1559,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)
@@ -1590,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,
@@ -1603,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)
 {
@@ -1666,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);