From 278945f12726692bc8b148ea1a59697a1c01405a Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 14 Nov 2022 17:58:12 -0500 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 --- 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 | 8 +++ shell/wayland/display.h | 3 + shell/wayland/window.h | 2 + 9 files changed, 148 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 6bdc75b..a599f95 100644 --- a/cmake/plugins.cmake +++ b/cmake/plugins.cmake @@ -101,4 +101,9 @@ if (BUILD_PLUGIN_SECURE_STORAGE) pkg_check_modules(PLUGIN_SECURE_STORAGE REQUIRED libsecret-1) 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 ad0c83c..9ce346d 100644 --- a/shell/engine.cc +++ b/shell/engine.cc @@ -595,3 +595,9 @@ MAYBE_UNUSED TextInput* Engine::GetTextInput() const { } #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 501ba4b..4193e7e 100644 --- a/shell/engine.h +++ b/shell/engine.h @@ -50,6 +50,12 @@ class TextInput; #endif +#if ENABLE_PLUGIN_AGL_SHELL + +class Display; + +#endif + class Engine { public: Engine(FlutterView* view, @@ -146,6 +152,10 @@ class Engine { #endif +#if ENABLE_PLUGIN_AGL_SHELL + std::shared_ptr GetDisplay() const; +#endif + Backend* GetBackend() { return m_backend; } diff --git a/shell/platform_channel.cc b/shell/platform_channel.cc index 10f4715..2c7ab8c 100644 --- a/shell/platform_channel.cc +++ b/shell/platform_channel.cc @@ -53,6 +53,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; @@ -101,4 +104,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..81627b6 --- /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..747eb36 --- /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 5d78471..48262c3 100644 --- a/shell/wayland/display.cc +++ b/shell/wayland/display.cc @@ -697,6 +697,14 @@ void Display::AglShellDoPanel(struct wl_surface* surface, } } +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::AglShellDoReady() { if (m_agl_shell) { agl_shell_ready(m_agl_shell); diff --git a/shell/wayland/display.h b/shell/wayland/display.h index bf05b27..c628c8c 100644 --- a/shell/wayland/display.h +++ b/shell/wayland/display.h @@ -82,6 +82,9 @@ class Display { enum agl_shell_edge mode, size_t index); + void AglShellDoActivate(const std::string& app_id, + size_t index); + void AglShellDoReady(); void SetEngine(wl_surface* surface, Engine* engine); diff --git a/shell/wayland/window.h b/shell/wayland/window.h index 4b5c726..b4d0be3 100644 --- a/shell/wayland/window.h +++ b/shell/wayland/window.h @@ -81,6 +81,8 @@ class WaylandWindow { uint32_t m_fps_counter; static window_type get_window_type(const std::string& type); + std::shared_ptr GetDisplay() { return m_display; } + private: struct shm_buffer { struct wl_buffer* buffer; -- 2.38.1