提交 d4579e95 编写于 作者: N Night 提交者: night_xiaoye

window: fix crasher because of X11_XSetICFocus.

x11 impliments(X11_XSetICFocus, X11_XUnsetICFocus, X11_XDestroyIC, X11_XCreateIC) are "thread safe".
In anbox, they are called by SDL_WaitForEventTimeout, SDL_CreateWindow, SDL_DestroyWindow.
But origin anbox code sets them in different thread, and then crashed in a low probability.
This commit sets them in the same thread to avoid this crash.
上级 6dbb2840
......@@ -38,6 +38,22 @@ namespace input {
class Manager;
} // namespace input
namespace platform {
enum User_Event {
USER_CREATE_WINDOW,
USER_DESTROY_WINDOW
};
struct manager_window_param {
int windowId = 0;
graphics::Rect rect;
std::string title;
manager_window_param (int id, graphics::Rect r, std::string t):
windowId(id),
rect(r),
title(t)
{}
};
class BasePlatform {
public:
virtual ~BasePlatform() {}
......@@ -58,6 +74,7 @@ class BasePlatform {
virtual void set_window_manager(const std::shared_ptr<wm::Manager> &window_manager) = 0;
virtual bool supports_multi_window() const = 0;
virtual int get_register_event() const = 0;
};
struct Configuration {
......
......@@ -71,5 +71,10 @@ void NullPlatform::set_window_manager(const std::shared_ptr<wm::Manager> &window
bool NullPlatform::supports_multi_window() const {
return false;
}
int NullPlatform::get_register_event() const {
ERROR("Not implemented");
return -1;
}
} // namespace wm
} // namespace anbox
......@@ -36,6 +36,7 @@ class NullPlatform : public BasePlatform {
void set_renderer(const std::shared_ptr<Renderer> &renderer) override;
void set_window_manager(const std::shared_ptr<wm::Manager> &window_manager) override;
bool supports_multi_window() const override;
int get_register_event() const override;
};
} // namespace wm
} // namespace anbox
......
......@@ -131,6 +131,8 @@ Platform::Platform(
event_thread_ = std::thread(&Platform::process_events, this);
ime_thread_ = std::thread(&Platform::create_ime_socket, this);
register_event = SDL_RegisterEvents(1);
}
Platform::~Platform() {
......@@ -241,6 +243,28 @@ void Platform::process_events() {
}
break;
default:
if (event.type == register_event) {
int event_type = event.user.code;
manager_window_param* param = (manager_window_param*) event.user.data1;
if (param) {
if (event_type == USER_CREATE_WINDOW) {
auto w = create_window(param->windowId, param->rect, param->title);
if (w) {
w->attach();
window_manager_->insert_task(param->windowId, w);
} else {
WARNING("create window failed! remove task on android!");
window_manager_->remove_task(param->windowId);
}
} else if (event_type == USER_DESTROY_WINDOW) {
window_manager_->erase_task(param->windowId);
}
delete param;
param = nullptr;
} else {
ERROR("null point param!!");
}
}
break;
}
}
......
......@@ -74,6 +74,8 @@ class Platform : public std::enable_shared_from_this<Platform>,
bool supports_multi_window() const override;
int get_register_event() const override {return register_event;}
private:
void process_events();
void process_input_event(const SDL_Event &event);
......@@ -118,6 +120,8 @@ class Platform : public std::enable_shared_from_this<Platform>,
void push_finger_down(int x, int y, int finger_id, std::vector<input::Event> &touch_events);
void push_finger_up(int finger_id, std::vector<input::Event> &touch_events);
void push_finger_motion(int x, int y, int finger_id, std::vector<input::Event> &touch_events);
int register_event = 0;
};
} // namespace sdl
} // namespace platform
......
......@@ -39,6 +39,8 @@ class Manager {
const std::int32_t &resize_mode) = 0;
virtual void set_focused_task(const Task::Id &task) = 0;
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;
// FIXME only applies for the multi-window case
virtual std::shared_ptr<Window> find_window_for_task(const Task::Id &task) = 0;
......
......@@ -20,6 +20,7 @@
#include "anbox/platform/base_platform.h"
#include "anbox/bridge/android_api_stub.h"
#include "anbox/logger.h"
#include <SDL2/SDL.h>
#include <algorithm>
......@@ -34,8 +35,6 @@ MultiWindowManager::~MultiWindowManager() {}
void MultiWindowManager::apply_window_state_update(const WindowState::List &updated,
const WindowState::List &removed) {
std::lock_guard<std::mutex> l(mutex_);
// Base on the update we get from the Android WindowManagerService we will
// create different window instances with the properties supplied. Incoming
// layer updates from SurfaceFlinger will be mapped later into those windows
......@@ -43,14 +42,6 @@ void MultiWindowManager::apply_window_state_update(const WindowState::List &upda
std::map<Task::Id, WindowState::List> task_updates;
printf("=================================\n");
for (const auto &window : updated) {
printf("updated:%d\n", window.task());
}
for (const auto &window : removed) {
printf("removed:%d\n", removed.task());
}
printf("##########\n");
for (const auto &window : updated) {
// Ignore all windows which are not part of the freeform task stack
if (window.stack() != Stack::Id::Freeform) continue;
......@@ -60,13 +51,12 @@ void MultiWindowManager::apply_window_state_update(const WindowState::List &upda
// If we know that task already we first collect all window updates
// for it so we can apply all of them together.
auto w = windows_.find(window.task());
if (w != windows_.end()) {
auto t = task_updates.find(window.task());
if (t == task_updates.end())
task_updates.insert({window.task(), {window}});
else
task_updates[window.task()].push_back(window);
auto t = task_updates.find(window.task());
if (t == task_updates.end())
task_updates.insert({window.task(), {window}});
else
task_updates[window.task()].push_back(window);
if (find_window_for_task(window.task()) != nullptr) {
continue;
}
......@@ -76,65 +66,44 @@ void MultiWindowManager::apply_window_state_update(const WindowState::List &upda
auto title = window.package_name();
auto app = app_db_->find_by_package(window.package_name());
if (app.valid())
if (app.valid()) {
title = app.name;
}
if (auto p = platform_.lock()) {
auto w = p->create_window(window.task(), window.frame(), title);
if (w) {
w->attach();
printf("update window: %d\n", window.task());
windows_.insert({window.task(), w});
} else {
// FIXME can we call this here safely or do we need to schedule the removal?
remove_task(window.task());
}
SDL_Event event;
SDL_memset(&event, 0, sizeof(event));
event.type = p->get_register_event();
event.user.code = platform::USER_CREATE_WINDOW;
event.user.data1 = new(std::nothrow) platform::manager_window_param(window.task(), window.frame(), title);
event.user.data2 = 0;
SDL_PushEvent(&event);
}
}
// Send updates we collected per task down to the corresponding window
// so that they can update themself.
for (const auto &u : task_updates) {
auto w = windows_.find(u.first);
if (w == windows_.end()) continue;
w->second->update_state(u.second);
}
// remove black window which appear after close sometimes
for (std::set<Task::Id>::iterator it = need_removed.begin(); it != need_removed.end();) {
auto w = windows_.find(*it);
if (w == windows_.end()) {
it = need_removed.erase(it);
printf("need_removed window: %d\n", *it);
} else if (task_updates.find(*it) == task_updates.end()) {
auto platform_window = w->second;
printf("need_removed window: %d\n", *it);
{
// As final step we process all windows we need to remove as they
// got killed on the other side. We need to respect here that we
// also get removals for windows which are part of a task which is
// still in use by other windows.
std::lock_guard<std::mutex> l(mutex_);
for (auto it = windows_.begin(); it != windows_.end(); ++it) {
auto w = task_updates.find(it->first);
if (w != task_updates.end()) {
it->second->update_state(w->second);
continue;
}
auto platform_window = it->second;
platform_window->release();
windows_.erase(w);
it = need_removed.erase(it);
} else {
++it;
}
}
// As final step we process all windows we need to remove as they
// got killed on the other side. We need to respect here that we
// also get removals for windows which are part of a task which is
// still in use by other windows.
for (const auto &window : removed) {
auto w = windows_.find(window.task());
if (w == windows_.end()) continue;
if (task_updates.find(window.task()) == task_updates.end()) {
auto platform_window = w->second;
platform_window->release();
windows_.erase(w);
printf("removed window: %d\n", window.task());
} else {
need_removed.insert(window.task());
printf("insert need_removed window: %d\n", window.task());
if (auto p = platform_.lock()) {
SDL_Event event;
SDL_memset(&event, 0, sizeof(event));
event.type = p->get_register_event();
event.user.code = platform::USER_DESTROY_WINDOW;
event.user.data1 = new(std::nothrow) platform::manager_window_param(it->first, graphics::Rect(0, 0, 0, 0), "");
event.user.data2 = 0;
SDL_PushEvent(&event);
}
}
}
}
......@@ -159,5 +128,18 @@ void MultiWindowManager::set_focused_task(const Task::Id &task) {
void MultiWindowManager::remove_task(const Task::Id &task) {
android_api_stub_->remove_task(task);
}
void MultiWindowManager::insert_task(const Task::Id &task, std::shared_ptr<wm::Window> pt) {
std::lock_guard<std::mutex> l(mutex_);
windows_.insert({ task, pt });
}
void MultiWindowManager::erase_task(const Task::Id &task) {
std::lock_guard<std::mutex>l(mutex_);
auto it = windows_.find(task);
if (it != windows_.end()) {
windows_.erase(it);
}
}
} // namespace wm
} // namespace anbox
......@@ -51,6 +51,8 @@ class MultiWindowManager : public Manager {
const std::int32_t &resize_mode) override;
void set_focused_task(const Task::Id &task) override;
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;
private:
std::mutex mutex_;
......@@ -58,8 +60,6 @@ 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::set<Task::Id> need_removed;
};
} // namespace wm
} // namespace anbox
......
......@@ -75,5 +75,14 @@ void SingleWindowManager::remove_task(const Task::Id &task) {
// application.
kill(getpid(), SIGTERM);
}
void SingleWindowManager::insert_task(const Task::Id &task, std::shared_ptr<wm::Window> pt) {
(void)task;
(void)pt;
}
void SingleWindowManager::erase_task(const Task::Id &task) {
(void)task;
}
} // namespace wm
} // namespace anbox
......@@ -50,6 +50,8 @@ class SingleWindowManager : public Manager {
const std::int32_t &resize_mode) override;
void set_focused_task(const Task::Id &task) override;
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;
private:
std::weak_ptr<platform::BasePlatform> platform_;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册