From 413898c43c8f66a7d49fe8bb74a85ce67733bc86 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 1 Jun 2023 14:34:03 -0400 Subject: [PATCH] Add optional agl_shell plugin Add an optional agl_shell static plugin to expose the activate_app call from the agl-shell Wayland protocol that is used when running against the AGL compositor. This provides a way for a homescreen application to activate other application surfaces to switch between multiple applications as is needed for the AGL demo. Upstream-Status: Pending Signed-off-by: Scott Murray [Updated to work with upstream OSS 0223 release] Signed-off-by: Marius Vlad --- cmake/plugins.cmake | 5 ++ shell/engine.cc | 6 ++ shell/engine.h | 10 +++ shell/platform_channel.cc | 6 ++ shell/static_plugins/agl_shell/agl_shell.cc | 77 +++++++++++++++++++++ shell/static_plugins/agl_shell/agl_shell.h | 31 +++++++++ shell/wayland/display.cc | 7 ++ shell/wayland/display.h | 8 +++ shell/wayland/window.h | 2 + 9 files changed, 152 insertions(+) create mode 100644 shell/static_plugins/agl_shell/agl_shell.cc create mode 100644 shell/static_plugins/agl_shell/agl_shell.h diff --git a/cmake/plugins.cmake b/cmake/plugins.cmake index b720dca..20a55d7 100644 --- a/cmake/plugins.cmake +++ b/cmake/plugins.cmake @@ -123,4 +123,9 @@ if (BUILD_PLUGIN_SECURE_STORAGE) endif () +option(BUILD_PLUGIN_AGL_SHELL "Includes AGL Shell Wayland Protocol Plugin" OFF) +if (BUILD_PLUGIN_AGL_SHELL) + ENABLE_PLUGIN(agl_shell) +endif () + message(STATUS "Plugin Config .......... ${PLUGINS}") diff --git a/shell/engine.cc b/shell/engine.cc index d20b6ba..a0e38e9 100644 --- a/shell/engine.cc +++ b/shell/engine.cc @@ -614,3 +614,9 @@ MAYBE_UNUSED TextInput* Engine::GetTextInput() const { return m_key_event; } #endif + +#if ENABLE_PLUGIN_AGL_SHELL +std::shared_ptr Engine::GetDisplay() const { + return m_egl_window->GetDisplay(); +} +#endif diff --git a/shell/engine.h b/shell/engine.h index 94808dc..3a06f51 100644 --- a/shell/engine.h +++ b/shell/engine.h @@ -60,6 +60,12 @@ class KeyEvent; #endif +#if ENABLE_PLUGIN_AGL_SHELL + +class Display; + +#endif + class Engine { public: /** @@ -445,6 +451,10 @@ class Engine { MAYBE_UNUSED NODISCARD KeyEvent* GetKeyEvent() const; #endif +#if ENABLE_PLUGIN_AGL_SHELL + std::shared_ptr GetDisplay() const; +#endif + /** * @brief Get backend of view * @return Backend* diff --git a/shell/platform_channel.cc b/shell/platform_channel.cc index b72156a..81d7cb5 100644 --- a/shell/platform_channel.cc +++ b/shell/platform_channel.cc @@ -62,6 +62,9 @@ #ifdef ENABLE_PLUGIN_SECURE_STORAGE #include "static_plugins/secure_storage/secure_storage.h" #endif +#ifdef ENABLE_PLUGIN_AGL_SHELL +#include "static_plugins/agl_shell/agl_shell.h" +#endif PlatformChannel* PlatformChannel::singleton = nullptr; @@ -122,4 +125,7 @@ PlatformChannel::PlatformChannel() { RegisterCallback(SecureStorage::kChannelName, &SecureStorage::OnPlatformMessage); #endif +#ifdef ENABLE_PLUGIN_AGL_SHELL + RegisterCallback(AglShell::kChannelName, &AglShell::OnPlatformMessage); +#endif } diff --git a/shell/static_plugins/agl_shell/agl_shell.cc b/shell/static_plugins/agl_shell/agl_shell.cc new file mode 100644 index 0000000..e6160a5 --- /dev/null +++ b/shell/static_plugins/agl_shell/agl_shell.cc @@ -0,0 +1,77 @@ +// Copyright 2020 Toyota Connected North America +// Copyright 2022 Konsulko Group +// +// 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 "agl_shell.h" + +#include +#include + +#include "engine.h" +#include "wayland/display.h" + +#include + +void AglShell::OnPlatformMessage(const FlutterPlatformMessage* message, + void* userdata) { + std::unique_ptr> result; + auto engine = reinterpret_cast(userdata); + auto& codec = flutter::StandardMethodCodec::GetInstance(); + auto obj = codec.DecodeMethodCall(message->message, message->message_size); + + auto method = obj->method_name(); + if (method == kMethodActivateApp) { + if (obj->arguments()->IsNull()) { + result = codec.EncodeErrorEnvelope("argument_error", "Invalid Arguments"); + goto done; + } + + auto args = std::get_if(obj->arguments()); + if (!args) { + result = codec.EncodeErrorEnvelope("argument_error", "Invalid Arguments"); + goto done; + } + + std::string app_id; + auto it = args->find(flutter::EncodableValue("app_id")); + if (it != args->end()) { + app_id = std::get(it->second); + } + + int32_t index = 0; + it = args->find(flutter::EncodableValue("index")); + if (it != args->end()) { + index = std::get(it->second); + } + + if (app_id.empty() || index < 0) { + result = codec.EncodeErrorEnvelope("argument_error", "Invalid Arguments"); + goto done; + } + + auto display = engine->GetDisplay(); + if (display) { + display->AglShellDoActivate(app_id, index); + } + auto val = flutter::EncodableValue(true); + result = codec.EncodeSuccessEnvelope(&val); + } else { + FML_DLOG(INFO) << "AglShell: " << method << " is unhandled"; + result = codec.EncodeErrorEnvelope("unhandled_method", "Unhandled Method"); + } + +done: + engine->SendPlatformMessageResponse(message->response_handle, result->data(), + result->size()); +} diff --git a/shell/static_plugins/agl_shell/agl_shell.h b/shell/static_plugins/agl_shell/agl_shell.h new file mode 100644 index 0000000..698e44c --- /dev/null +++ b/shell/static_plugins/agl_shell/agl_shell.h @@ -0,0 +1,31 @@ +/* + * Copyright 2020 Toyota Connected North America + * Copyright 2022 Konsulko Group + * + * 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. + */ + +#pragma once + +#include + +class AglShell { + public: + static constexpr char kChannelName[] = "flutter/agl_shell"; + + static void OnPlatformMessage(const FlutterPlatformMessage* message, + void* userdata); + + private: + static constexpr char kMethodActivateApp[] = "activate_app"; +}; diff --git a/shell/wayland/display.cc b/shell/wayland/display.cc index 434dd05..99aa5ff 100644 --- a/shell/wayland/display.cc +++ b/shell/wayland/display.cc @@ -869,6 +869,13 @@ void Display::AglShellDoSetupActivationArea(uint32_t x, width, height); } +void Display::AglShellDoActivate(const std::string& app_id, size_t index) { + if (m_agl.shell) { + agl_shell_activate_app(m_agl.shell, app_id.c_str(), + m_all_outputs[index]->output); + } +} + void Display::SetEngine(wl_surface* surface, Engine* engine) { m_active_engine = engine; m_active_surface = surface; diff --git a/shell/wayland/display.h b/shell/wayland/display.h index 06b0f8b..ef6ea3f 100644 --- a/shell/wayland/display.h +++ b/shell/wayland/display.h @@ -150,6 +150,14 @@ class Display { */ void AglShellDoReady() const; + /** + * @brief AglShellDoActivate: + * @return void + * @relation + * wayland, agl-shell + */ + void AglShellDoActivate(const std::string& app_id, size_t index); + /** * @brief AglShell: Set up an activation area where to display the client's * window diff --git a/shell/wayland/window.h b/shell/wayland/window.h index d5e3c77..677dbdc 100644 --- a/shell/wayland/window.h +++ b/shell/wayland/window.h @@ -129,6 +129,8 @@ class WaylandWindow { return std::pair{m_geometry.width, m_geometry.height}; } + std::shared_ptr GetDisplay() { return m_display; } + private: size_t m_index; std::shared_ptr m_display;