From 424290f5a49ba4e96ed090030366fb7a462c765d Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Wed, 22 Jul 2020 13:31:00 +0300 Subject: [PATCH] homescreen/homescreen: Bind to agl_shell_desktop Bind to agl-shell-desktop protocol. Useful to propage events from to QML about applications launched. Signed-off-by: Marius Vlad --- homescreen/homescreen.pro | 3 +- homescreen/protocol/agl-shell-desktop.xml | 142 ++++++++++++++++++++++++++++++ homescreen/src/main.cpp | 85 ++++++++++++++---- homescreen/src/shell.h | 10 ++- 4 files changed, 219 insertions(+), 21 deletions(-) create mode 100644 homescreen/protocol/agl-shell-desktop.xml diff --git a/homescreen/homescreen.pro b/homescreen/homescreen.pro index ca9ea3b..ae705f9 100644 --- a/homescreen/homescreen.pro +++ b/homescreen/homescreen.pro @@ -63,4 +63,5 @@ RESOURCES += \ WAYLANDCLIENTSOURCES += \ - protocol/agl-shell.xml + protocol/agl-shell.xml \ + protocol/agl-shell-desktop.xml diff --git a/homescreen/protocol/agl-shell-desktop.xml b/homescreen/protocol/agl-shell-desktop.xml new file mode 100644 index 0000000..e8ae153 --- /dev/null +++ b/homescreen/protocol/agl-shell-desktop.xml @@ -0,0 +1,142 @@ + + + + Copyright © 2020 Collabora, Ltd. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + This extension can be used by regular application to instruct to compositor + to activate or switch to other running (regular) applications. The client + is responsbile for filtering their own app_id when receiving application id. + + The compositor will allow clients to bind to this interface only if the + policy engine allows it. + + + + + + + + + + + + + + + + + + The compositor may choose to advertise one or more application ids which + can be used to activate/switch to. + + When this global is bound, the compositor will send all application ids + available for activation, but may send additional application id at any + time (when they've been mapped in the compositor). + + + + + + + Ask the compositor to make a toplevel to become the current/focused + window for window management purposes. + + See xdg_toplevel.set_app_id from the xdg-shell protocol for a + description of app_id. + + + + + + + + + Ask the compositor to make a top-level window obey the 'app_role' enum + and, depending on that role, to use some of the arguments as initial + values to take into account. + + Note that x, y, bx, by, width and height would only make sense for the + pop-up role, with the output argument being applicable to all the roles. + The width and height values define the maximum area which the + top-level window should be placed into. Note this doesn't correspond to + top-level surface size, but to a bounding box which will be used to + clip the surface to, in case the surface area extends that of this + bounding box. Both of these values need to be larger than 0 (zero) to be + taken into account by the compositor. Any negative values for the width + and height will be discarded. + + The x and y values will serve as the (initial) position values. + The bx and by values are the top-left x and y value of the bounding box. + Any clipping happening to the bounding box will not affect the surface + size or the position of the underlying surface backing the top-level + window. The bx and by values, like the positional values, could be + both set to zero, or even negative values. The compositor will pass + those on without any further validation. + + The initial position values and the bounding rectangle will still be + in effect on a subsequent activation request of the 'app_id', assuming + it was previously de-activated at some point in time. + + See xdg_toplevel.set_app_id from the xdg-shell protocol for a + description of app_id. + + + + + + + + + + + + + + + Ask the compositor to hide the toplevel window for window + management purposes. Depending on the window role, this request + will either display the previously active window (or the background + in case there's no previously activate surface) or temporarly (or + until a 'activate_app' is called upon) hide the surface. All + the surfaces are identifiable by using the app_id, and no actions are + taken in case the app_id is not/was not present. + + See xdg_toplevel.set_app_id from the xdg-shell protocol for a + description of app_id. + + + + + + + Notifies application(s) when other application have suffered state modifications. + + + + + + + + + diff --git a/homescreen/src/main.cpp b/homescreen/src/main.cpp index 742daa6..2d9ac4d 100644 --- a/homescreen/src/main.cpp +++ b/homescreen/src/main.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH * Copyright (c) 2017, 2018 TOYOTA MOTOR CORPORATION + * Copyright (c) 2020 Collabora, Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,18 +40,53 @@ #include #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; +}; + +static void +application_id_event(void *data, struct agl_shell_desktop *agl_shell_desktop, + const char *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) +{ +} + +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) + const char *interface, uint32_t version) { - struct agl_shell **shell = static_cast(data); + struct shell_container *sc = static_cast(data); if (strcmp(interface, agl_shell_interface.name) == 0) { - *shell = static_cast( + sc->agl_shell = static_cast( 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( + wl_registry_bind(reg, name, &agl_shell_desktop_interface, 1) + ); + + agl_shell_desktop_add_listener(sc->agl_shell_desktop, + &agl_shell_desktop_listener, sc); } } @@ -83,25 +119,33 @@ getWlOutput(QPlatformNativeInterface *native, QScreen *screen) } -static struct agl_shell * +static struct shell_container * register_agl_shell(QPlatformNativeInterface *native) { struct wl_display *wl; struct wl_registry *registry; - struct agl_shell *shell = nullptr; + struct shell_container *sc = new shell_container(); wl = static_cast( native->nativeResourceForIntegration("display") ); registry = wl_display_get_registry(wl); - wl_registry_add_listener(registry, ®istry_listener, &shell); + 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); - return shell; + if (!sc->agl_shell) { + delete sc; + } + + if (!sc->agl_shell_desktop) { + delete sc; + } + + return sc; } static struct wl_surface * @@ -137,13 +181,14 @@ find_screen(const char *screen_name) static void load_agl_shell_app(QPlatformNativeInterface *native, QQmlApplicationEngine *engine, - struct agl_shell *agl_shell, QUrl &bindingAddress, + struct shell_container *sc, QUrl &bindingAddress, const char *screen_name) { struct wl_surface *bg, *top, *bottom; struct wl_output *output; QObject *qobj_bg, *qobj_top, *qobj_bottom; QScreen *screen = nullptr; + struct agl_shell *agl_shell = sc->agl_shell; QQmlComponent bg_comp(engine, QUrl("qrc:/background.qml")); qInfo() << bg_comp.errors(); @@ -192,9 +237,10 @@ int main(int argc, char *argv[]) setenv("QT_QPA_PLATFORM", "wayland", 1); QGuiApplication a(argc, argv); const char *screen_name; + int ret; QPlatformNativeInterface *native = qApp->platformNativeInterface(); - struct agl_shell *agl_shell = nullptr; + struct shell_container *sc = nullptr; screen_name = getenv("HOMESCREEN_START_SCREEN"); QCoreApplication::setOrganizationDomain("LinuxFoundation"); @@ -223,15 +269,17 @@ int main(int argc, char *argv[]) HMI_DEBUG("HomeScreen","port = %d, token = %s", port, token.toStdString().c_str()); - agl_shell = register_agl_shell(native); - if (!agl_shell) { - fprintf(stderr, "agl_shell extension is not advertised. " - "Are you sure that agl-compositor is running?\n"); + sc = register_agl_shell(native); + if (!sc) { exit(EXIT_FAILURE); } - std::shared_ptr shell{agl_shell, agl_shell_destroy}; - Shell *aglShell = new Shell(shell, &a); + std::shared_ptr + shell{sc->agl_shell, agl_shell_destroy}; + std::shared_ptr + shell_desktop{sc->agl_shell_desktop, agl_shell_desktop_destroy}; + Shell *aglShell = new Shell(shell, shell_desktop, &a); + sc->a_shell = aglShell; // import C++ class to QML // qmlRegisterType("HomeScreen", 1, 0, "ApplicationLauncher"); @@ -270,7 +318,10 @@ int main(int argc, char *argv[]) /* instead of loading main.qml we load one-by-one each of the QMLs, * divided now between several surfaces: panels, background. */ - load_agl_shell_app(native, &engine, agl_shell, bindingAddress, screen_name); + load_agl_shell_app(native, &engine, sc, bindingAddress, screen_name); + + ret = a.exec(); - return a.exec(); + delete sc; + return ret; } diff --git a/homescreen/src/shell.h b/homescreen/src/shell.h index 8bf0e9b..0e7de82 100644 --- a/homescreen/src/shell.h +++ b/homescreen/src/shell.h @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Collabora Ltd. + * Copyright © 2019, 2020 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 #include #include "wayland-agl-shell-client-protocol.h" +#include "wayland-agl-shell-desktop-client-protocol.h" /* * Basic type to wrap the agl_shell wayland object into a QObject, so that it @@ -45,9 +46,12 @@ class Shell : public QObject public: std::shared_ptr shell; + std::shared_ptr shell_desktop; - Shell(std::shared_ptr shell, QObject *parent = nullptr) : - QObject(parent), shell(shell) + Shell(std::shared_ptr shell, + std::shared_ptr shell_desktop, + QObject *parent = nullptr) : + QObject(parent), shell(shell), shell_desktop(shell_desktop) {} public slots: void activate_app(QWindow *win, const QString &app_id); -- 2.16.6