From 9af877d3a775763d9199ffa897948f5009bd8a7b Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Wed, 4 Dec 2019 19:58:38 +1300 Subject: Add basic support for app switching --- homescreen/homescreen.pro | 6 ++++-- homescreen/protocol/agl-shell.xml | 17 +++++++++++++++ homescreen/qml/ShortcutArea.qml | 5 +++-- homescreen/src/main.cpp | 25 ++++++++++++---------- homescreen/src/shell.cpp | 35 +++++++++++++++++++++++++++++++ homescreen/src/shell.h | 44 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 117 insertions(+), 15 deletions(-) create mode 100644 homescreen/src/shell.cpp create mode 100644 homescreen/src/shell.h diff --git a/homescreen/homescreen.pro b/homescreen/homescreen.pro index 0ec86d4..0afb53b 100644 --- a/homescreen/homescreen.pro +++ b/homescreen/homescreen.pro @@ -27,7 +27,8 @@ SOURCES += \ src/statusbarmodel.cpp \ src/statusbarserver.cpp \ src/applicationlauncher.cpp \ - src/mastervolume.cpp + src/mastervolume.cpp \ + src/shell.cpp WAYLANDCLIENTSOURCES += \ protocol/agl-shell.xml @@ -36,7 +37,8 @@ HEADERS += \ src/statusbarmodel.h \ src/statusbarserver.h \ src/applicationlauncher.h \ - src/mastervolume.h + src/mastervolume.h \ + src/shell.h OTHER_FILES += \ README.md diff --git a/homescreen/protocol/agl-shell.xml b/homescreen/protocol/agl-shell.xml index 59548e7..5e31d98 100644 --- a/homescreen/protocol/agl-shell.xml +++ b/homescreen/protocol/agl-shell.xml @@ -96,5 +96,22 @@ + + + + Asks the compositor to make a toplevel to become the current/focued + window for window management purposes. + + See xdg_toplevel.set_app_id from the xdg-shell protocol for a + description app_id. + + If multiple toplevels have the same app_id, the result is unspecified. + + XXX: Do we need feedback to say it didn't work? (e.g. client does + not exist) + + + + diff --git a/homescreen/qml/ShortcutArea.qml b/homescreen/qml/ShortcutArea.qml index 9e404dc..d470231 100644 --- a/homescreen/qml/ShortcutArea.qml +++ b/homescreen/qml/ShortcutArea.qml @@ -18,6 +18,7 @@ import QtQuick 2.2 import QtQuick.Layouts 1.1 +import QtQuick.Window 2.2 Item { id: root @@ -25,7 +26,7 @@ Item { ListModel { id: applicationModel ListElement { - appid: 'launcher' + appid: "launcher" name: 'launcher' application: 'launcher@0.1' } @@ -59,7 +60,7 @@ Item { name: model.name active: model.name === launcher.current onClicked: { - homescreenHandler.tapShortcut(model.appid) + shell.activate_app(Window.window, model.appid) } } } diff --git a/homescreen/src/main.cpp b/homescreen/src/main.cpp index ae1fff8..98cec6f 100644 --- a/homescreen/src/main.cpp +++ b/homescreen/src/main.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -36,6 +37,7 @@ #include "statusbarmodel.h" #include "afm_user_daemon_proxy.h" #include "mastervolume.h" +#include "shell.h" #include "hmi-debug.h" #include "wayland-agl-shell-client-protocol.h" @@ -77,34 +79,35 @@ static const struct wl_registry_listener registry_listener = { static struct wl_surface *create_component(QPlatformNativeInterface *native, QQmlComponent *comp, QScreen *screen) { - QObject *obj = comp->create(); - obj->setParent(screen); + QObject *obj = comp->create(); + obj->setParent(screen); - QWindow *win = qobject_cast(obj); - return static_cast(native->nativeResourceForWindow("surface", win)); + QWindow *win = qobject_cast(obj); + return static_cast(native->nativeResourceForWindow("surface", win)); } int main(int argc, char *argv[]) { setenv("QT_QPA_PLATFORM", "wayland", 1); QGuiApplication a(argc, argv); - QPlatformNativeInterface *native = qApp->platformNativeInterface(); + QPlatformNativeInterface *native = qApp->platformNativeInterface(); struct wl_display *wl; struct wl_registry *registry; struct agl_shell *agl_shell = nullptr; - wl = static_cast(native->nativeResourceForIntegration("display")); + wl = static_cast(native->nativeResourceForIntegration("display")); registry = wl_display_get_registry(wl); wl_registry_add_listener(registry, ®istry_listener, &agl_shell); // Roundtrip to get all globals advertised by the compositor wl_display_roundtrip(wl); wl_registry_destroy(registry); - + if (!agl_shell) { qFatal("Compositor does not support AGL shell protocol"); return 1; } + std::shared_ptr shell{agl_shell, agl_shell_destroy}; // use launch process QScopedPointer afm_user_daemon_proxy(new org::AGL::afm::user("org.AGL.afm.user", @@ -171,7 +174,7 @@ int main(int argc, char *argv[]) QQuickWindow *window = qobject_cast(root); for (auto o : root_objects) { - qDebug() << o->dynamicPropertyNames(); + qDebug() << o->dynamicPropertyNames(); } QList sobjs = engine.rootObjects(); @@ -185,6 +188,7 @@ int main(int argc, char *argv[]) context->setContextProperty("launcher", launcher); context->setContextProperty("weather", new Weather(bindingAddress)); context->setContextProperty("bluetooth", new Bluetooth(bindingAddress, engine.rootContext())); + context->setContextProperty("shell", new Shell(shell, &a)); QQmlComponent bg_comp(&engine, QUrl("qrc:/background.qml")); QQmlComponent top_comp(&engine, QUrl("qrc:/toppanel.qml")); @@ -206,9 +210,8 @@ int main(int argc, char *argv[]) } // Delay the ready signal until after Qt has done all of its own setup in a.exec() - QTimer::singleShot(0, [agl_shell](){ - agl_shell_ready(agl_shell); - agl_shell_destroy(agl_shell); + QTimer::singleShot(0, [shell](){ + agl_shell_ready(shell.get()); }); return a.exec(); diff --git a/homescreen/src/shell.cpp b/homescreen/src/shell.cpp new file mode 100644 index 0000000..b4dd98d --- /dev/null +++ b/homescreen/src/shell.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019 Collabora Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "shell.h" +#include +#include + +void Shell::activate_app(QWindow *win, const QString &app_id) +{ + QPlatformNativeInterface *native = qApp->platformNativeInterface(); + QScreen *screen = win->screen(); + struct wl_output *output; + + output = static_cast(native->nativeResourceForScreen( + "output", const_cast(screen))); + + agl_shell_activate_app(this->shell.get(), + app_id.toStdString().c_str(), + output); +} diff --git a/homescreen/src/shell.h b/homescreen/src/shell.h new file mode 100644 index 0000000..c5e0b18 --- /dev/null +++ b/homescreen/src/shell.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 Collabora Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SHELLHANDLER_H +#define SHELLHANDLER_H + +#include +#include +#include +#include +#include +#include "wayland-agl-shell-client-protocol.h" + +/* + * Basic type to wrap the agl_shell wayland object into a QObject, so that it + * can be used in callbacks from QML. + */ + +class Shell : public QObject +{ + Q_OBJECT + std::shared_ptr shell; +public: + Shell(std::shared_ptr shell, QObject *parent = nullptr) : + QObject(parent), shell(shell) + {} +public slots: + void activate_app(QWindow *win, const QString &app_id); +}; + +#endif // SHELLHANDLER_H -- cgit 1.2.3-korg