+#include <qpa/qplatformnativeinterface.h>
+#include <wayland-client.h>
+
+#include "wayland-agl-shell-client-protocol.h"
+#include "wayland-agl-shell-desktop-client-protocol.h"
+#include "shell.h"
+
+struct shell_container {
+ struct agl_shell *agl_shell;
+ struct agl_shell_desktop *agl_shell_desktop;
+ // used to propagate events from C/C++ event handlers from the protocol
+ // to the QML in case we need them
+ Shell *a_shell;
+ ApplicationLauncher *launcher;
+};
+
+static void
+application_id_event(void *data, struct agl_shell_desktop *agl_shell_desktop,
+ const char *app_id)
+{
+ // this event is sent only when surfaces are being created. we call
+ // setCurrent() to take care of this the first time, with later state
+ // event changes being handled by the application_state_event()
+ struct shell_container *sc = static_cast<struct shell_container *>(data);
+ sc->launcher->setCurrent(QString(app_id));
+}
+
+static void
+application_state_event(void *data, struct agl_shell_desktop *agl_shell_desktop,
+ const char *app_id, const char *app_data,
+ uint32_t app_state, uint32_t app_role)
+{
+ struct shell_container *sc = static_cast<struct shell_container *>(data);
+ sc->launcher->setCurrent(QString(app_id));
+}
+
+static const struct agl_shell_desktop_listener agl_shell_desktop_listener = {
+ application_id_event,
+ application_state_event,
+};
+
+
+static void
+global_add(void *data, struct wl_registry *reg, uint32_t name,
+ const char *interface, uint32_t version)
+{
+ struct shell_container *sc = static_cast<struct shell_container *>(data);
+
+ if (strcmp(interface, agl_shell_interface.name) == 0) {
+ sc->agl_shell = static_cast<struct agl_shell *>(
+ wl_registry_bind(reg, name, &agl_shell_interface, 1)
+ );
+ } else if (strcmp(interface, agl_shell_desktop_interface.name) == 0) {
+ sc->agl_shell_desktop = static_cast<struct agl_shell_desktop *>(
+ wl_registry_bind(reg, name, &agl_shell_desktop_interface, 1)
+ );
+
+ agl_shell_desktop_add_listener(sc->agl_shell_desktop,
+ &agl_shell_desktop_listener, sc);
+ }
+}
+
+static void
+global_remove(void *data, struct wl_registry *reg, uint32_t id)
+{
+ /* Don't care */
+ (void) data;
+ (void) reg;
+ (void) id;
+}
+
+static const struct wl_registry_listener registry_listener = {
+ global_add,
+ global_remove,
+};
+
+static struct wl_surface *
+getWlSurface(QPlatformNativeInterface *native, QWindow *window)
+{
+ void *surf = native->nativeResourceForWindow("surface", window);
+ return static_cast<struct ::wl_surface *>(surf);
+}
+
+static struct wl_output *
+getWlOutput(QPlatformNativeInterface *native, QScreen *screen)
+{
+ void *output = native->nativeResourceForScreen("output", screen);
+ return static_cast<struct ::wl_output*>(output);
+}
+
+
+static struct shell_container *
+register_agl_shell(QPlatformNativeInterface *native)
+{
+ struct wl_display *wl;
+ struct wl_registry *registry;
+ struct shell_container *sc = new shell_container();
+
+ wl = static_cast<struct wl_display *>(
+ native->nativeResourceForIntegration("display")
+ );
+ registry = wl_display_get_registry(wl);
+
+ wl_registry_add_listener(registry, ®istry_listener, sc);
+
+ /* Roundtrip to get all globals advertised by the compositor */
+ wl_display_roundtrip(wl);
+ wl_registry_destroy(registry);
+
+ if (!sc->agl_shell) {
+ delete sc;
+ }
+
+ if (!sc->agl_shell_desktop) {
+ delete sc;
+ }
+
+ return sc;
+}
+
+static struct wl_surface *
+create_component(QPlatformNativeInterface *native, QQmlComponent *comp,
+ QScreen *screen, QObject **qobj)