提交 dffba606 编写于 作者: W wangpeiqiang

window: add toast window feature.

When a toast window show on the android, show it on pc too.
上级 db05591b
......@@ -277,6 +277,8 @@ set(SOURCES
anbox/platform/sdl/sdl_wrapper.h
anbox/platform/sdl/window.cpp
anbox/platform/sdl/window.h
anbox/platform/sdl/toast_window.cpp
anbox/platform/sdl/toast_window.h
anbox/protobuf/anbox_bridge.proto
anbox/protobuf/anbox_container.proto
......
......@@ -196,6 +196,7 @@ anbox::cmds::SessionManager::SessionManager()
platform->set_window_manager(window_manager);
platform->set_renderer(gl_server->renderer());
platform->create_toast_window();
window_manager->setup();
android_api_stub->set_platform(platform);
......
......@@ -18,6 +18,7 @@
#include "anbox/graphics/multi_window_composer_strategy.h"
#include "anbox/wm/manager.h"
#include "anbox/utils.h"
#include "anbox/logger.h"
namespace anbox {
namespace graphics {
......@@ -25,10 +26,27 @@ MultiWindowComposerStrategy::MultiWindowComposerStrategy(const std::shared_ptr<w
std::map<std::shared_ptr<wm::Window>, RenderableList> MultiWindowComposerStrategy::process_layers(const RenderableList &renderables) {
WindowRenderableList win_layers;
bool bGetToast = false; // if don't have toast frame, tell wm to hide toast_window
for (const auto &renderable : renderables) {
// Ignore all surfaces which are not meant for a task
if (!utils::string_starts_with(renderable.name(), "org.anbox.surface."))
if (renderable.name() == "Toast") {
if (bGetToast) {
WARNING("Toast! toast choosed");
continue;
}
auto w = wm_->update_toast_window(renderable.screen_position());
if (w) {
win_layers.insert({w, {renderable}});
} else {
ERROR("Toast! get toast window error");
continue;
}
bGetToast = true;
continue;
}
if (!utils::string_starts_with(renderable.name(), "org.anbox.surface.")) {
continue;
}
wm::Task::Id task_id = 0;
if (sscanf(renderable.name().c_str(), "org.anbox.surface.%d", &task_id) != 1 || !task_id)
......@@ -36,7 +54,6 @@ std::map<std::shared_ptr<wm::Window>, RenderableList> MultiWindowComposerStrateg
auto w = wm_->find_window_for_task(task_id);
if (!w) continue;
if (win_layers.find(w) == win_layers.end()) {
win_layers.insert({w, {renderable}});
continue;
......@@ -44,6 +61,9 @@ std::map<std::shared_ptr<wm::Window>, RenderableList> MultiWindowComposerStrateg
win_layers[w].push_back(renderable);
}
if (!bGetToast) { // hide toast window
wm_->update_toast_window(Rect(0, 0, 0, 0));
}
for (auto &w : win_layers) {
const auto &renderables = w.second;
......
......@@ -72,6 +72,7 @@ class BasePlatform {
virtual void set_renderer(const std::shared_ptr<Renderer> &renderer) = 0;
virtual void set_window_manager(const std::shared_ptr<wm::Manager> &window_manager) = 0;
virtual void create_toast_window() = 0;
virtual bool restore_app(const std::string &package_name) = 0;
virtual bool supports_multi_window() const = 0;
......
......@@ -87,5 +87,10 @@ std::string NullPlatform::ime_socket_file() const {
ERROR("Not implemented");
return "";
}
void NullPlatform::create_toast_window() {
ERROR("Not implemented");
}
} // namespace wm
} // namespace anbox
......@@ -36,6 +36,7 @@ class NullPlatform : public BasePlatform {
std::shared_ptr<audio::Source> create_audio_source() override;
void set_renderer(const std::shared_ptr<Renderer> &renderer) override;
void set_window_manager(const std::shared_ptr<wm::Manager> &window_manager) override;
void create_toast_window() override;
bool supports_multi_window() const override;
int get_user_window_event() const override;
std::string ime_socket_file() const override;
......
......@@ -26,6 +26,7 @@
#include "anbox/platform/sdl/audio_sink.h"
#include "anbox/platform/alsa/audio_source.h"
#include "anbox/system_configuration.h"
#include "anbox/platform/sdl/toast_window.h"
#include "anbox/wm/manager.h"
......@@ -155,6 +156,20 @@ void Platform::set_renderer(const std::shared_ptr<Renderer> &renderer) {
renderer_ = renderer;
}
void Platform::create_toast_window() {
/* This is used to create window to show toast message in android.
* In normal time, it is hided. When a toast frame comes in, show toast window.
* Run create_toast_window after set_renderer and set_window_manager, if not toast_window
* will have no use.
*/
auto w = std::make_shared<ToastWindow>(renderer_, anbox::graphics::Rect(0, 0, 0, 0));
if (window_manager_) {
window_manager_->set_toast_window(w);
} else {
WARNING("toast window set failed!!!");
}
}
void Platform::set_window_manager(const std::shared_ptr<wm::Manager> &window_manager) {
window_manager_ = window_manager;
}
......
......@@ -63,6 +63,7 @@ class Platform : public std::enable_shared_from_this<Platform>,
void set_renderer(const std::shared_ptr<Renderer> &renderer) override;
void set_window_manager(const std::shared_ptr<wm::Manager> &window_manager) override;
void create_toast_window() override;
void set_clipboard_data(const ClipboardData &data) override;
ClipboardData get_clipboard_data() override;
......
#include "anbox/platform/sdl/toast_window.h"
#include "anbox/logger.h"
namespace anbox {
namespace platform {
namespace sdl {
ToastWindow::ToastWindow(const std::shared_ptr<Renderer> &renderer, const graphics::Rect &frame)
: wm::Window(renderer, 0, frame, "toast") {
window_ = SDL_CreateWindow("toast", frame.left(), frame.top(), frame.width(), frame.height(),
SDL_WINDOW_BORDERLESS | SDL_WINDOW_TOOLTIP);
if (!window_) {
const auto message = utils::string_format("Failed to create window: %s", SDL_GetError());
return;
}
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(window_, &info);
switch (info.subsystem) {
#if defined(X11_SUPPORT)
case SDL_SYSWM_X11:
native_display_ = static_cast<EGLNativeDisplayType>(info.info.x11.display);
set_native_handle(static_cast<EGLNativeWindowType>(info.info.x11.window));
break;
#endif
#if defined(WAYLAND_SUPPORT)
case SDL_SYSWM_WAYLAND:
native_display_ = reinterpret_cast<EGLNativeDisplayType>(info.info.wl.display);
set_native_handle(reinterpret_cast<EGLNativeWindowType>(info.info.wl.surface));
break;
#endif
#if defined(MIR_SUPPORT)
case SDL_SYSWM_MIR: {
native_display_ = static_cast<EGLNativeDisplayType>(mir_connection_get_egl_native_display(info.info.mir.connection));
auto buffer_stream = mir_surface_get_buffer_stream(info.info.mir.surface);
set_native_handle(reinterpret_cast<EGLNativeWindowType>(mir_buffer_stream_get_egl_native_window(buffer_stream)));
break;
}
#endif
default:
ERROR("Unknown subsystem (%d)", info.subsystem);
}
SDL_HideWindow(window_);
attach();
}
ToastWindow::~ToastWindow() {
release();
}
void ToastWindow::update_state(const wm::WindowState::List &states) {
auto state = states[0];
if (state.stack() == wm::Stack::Id::Default) {
SDL_HideWindow(window_);
return;
}
if (frame() != state.frame()) {
SDL_SetWindowSize(window_, state.frame().width(), state.frame().height());
SDL_SetWindowPosition(window_, state.frame().left(), state.frame().top());
update_frame(state.frame());
}
SDL_ShowWindow(window_);
}
} // namespace sdl
} // namespace platform
} // namespace anbox
#ifndef ANBOX_PLATFORM_SDL_TOAST_WINDOW_H_
#define ANBOX_PLATFORM_SDL_TOAST_WINDOW_H_
#include "anbox/wm/window.h"
#include "anbox/platform/sdl/sdl_wrapper.h"
class Renderer;
namespace anbox {
namespace platform {
namespace sdl {
class ToastWindow : public std::enable_shared_from_this<ToastWindow>, public wm::Window {
public:
ToastWindow(const std::shared_ptr<Renderer> &renderer,
const graphics::Rect &frame);
~ToastWindow();
void update_state(const wm::WindowState::List &states) override;
private:
SDL_Window *window_;
EGLNativeDisplayType native_display_;
};
} // namespace sdl
} // namespace platform
} // namespace anbox
#endif
......@@ -41,10 +41,12 @@ class Manager {
virtual void remove_task(const Task::Id &task) = 0;
virtual void insert_task(const Task::Id &task, std::shared_ptr<wm::Window> pt) = 0;
virtual void erase_task(const Task::Id &task) = 0;
virtual std::shared_ptr<Window> update_toast_window(const anbox::graphics::Rect &rect) = 0;
virtual std::string get_title(const std::string &package_name) = 0;
// FIXME only applies for the multi-window case
virtual std::shared_ptr<Window> find_window_for_task(const Task::Id &task) = 0;
virtual void set_toast_window(std::shared_ptr<wm::Window> tw) = 0;
};
} // namespace wm
} // namespace anbox
......
......@@ -150,5 +150,29 @@ std::string MultiWindowManager::get_title(const std::string &package_name) {
return package_name;
}
}
std::shared_ptr<Window> MultiWindowManager::update_toast_window(const anbox::graphics::Rect &rect) {
auto stack = wm::Stack::Id::Freeform;
if (rect == graphics::Rect(0, 0, 0, 0)) {
stack = wm::Stack::Id::Default;
}
auto update_window = wm::WindowState{
wm::Display::Id{0},
true,
rect,
"",
wm::Task::Id{0},
stack,
};
if (toast_window_) {
toast_window_->update_state({update_window});
}
return toast_window_;
}
void MultiWindowManager::set_toast_window(std::shared_ptr<Window> tw) {
toast_window_ = tw;
}
} // namespace wm
} // namespace anbox
......@@ -53,6 +53,8 @@ class MultiWindowManager : public Manager {
void remove_task(const Task::Id &task) override;
void insert_task(const Task::Id &task, std::shared_ptr<wm::Window> pt) override;
void erase_task(const Task::Id &task) override;
std::shared_ptr<Window> update_toast_window(const anbox::graphics::Rect &rect) override;
void set_toast_window(std::shared_ptr<Window> tw) override;
std::string get_title(const std::string &package_name) override;
private:
......@@ -61,6 +63,7 @@ class MultiWindowManager : public Manager {
std::shared_ptr<bridge::AndroidApiStub> android_api_stub_;
std::shared_ptr<application::Database> app_db_;
std::map<Task::Id, std::shared_ptr<Window>> windows_;
std::shared_ptr<Window> toast_window_;
};
} // namespace wm
} // namespace anbox
......
......@@ -89,5 +89,15 @@ std::string SingleWindowManager::get_title(const std::string &package_name) {
(void)package_name;
return "";
}
std::shared_ptr<Window> SingleWindowManager::update_toast_window(const anbox::graphics::Rect &rect) {
(void)rect;
return nullptr;
}
void SingleWindowManager::set_toast_window(std::shared_ptr<Window> tw) {
(void)tw;
}
} // namespace wm
} // namespace anbox
......@@ -53,6 +53,8 @@ class SingleWindowManager : public Manager {
void insert_task(const Task::Id &task, std::shared_ptr<wm::Window> pt) override;
void erase_task(const Task::Id &task) override;
std::string get_title(const std::string &package_name) override;
std::shared_ptr<Window> update_toast_window(const anbox::graphics::Rect &rect) override;
void set_toast_window(std::shared_ptr<Window> tw) override;
private:
std::weak_ptr<platform::BasePlatform> platform_;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册