TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / wm / multi_window_manager.cpp
1 /*
2  * Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 3, as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranties of
10  * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11  * PURPOSE.  See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17
18 #include "anbox/application/database.h"
19 #include "anbox/wm/multi_window_manager.h"
20 #include "anbox/platform/base_platform.h"
21 #include "anbox/bridge/android_api_stub.h"
22 #include "anbox/logger.h"
23
24 #include <algorithm>
25
26 namespace anbox {
27 namespace wm {
28 MultiWindowManager::MultiWindowManager(const std::weak_ptr<platform::BasePlatform> &platform,
29                                        const std::shared_ptr<bridge::AndroidApiStub> &android_api_stub,
30                                        const std::shared_ptr<application::Database> &app_db)
31     : platform_(platform), android_api_stub_(android_api_stub), app_db_(app_db) {}
32
33 MultiWindowManager::~MultiWindowManager() {}
34
35 void MultiWindowManager::apply_window_state_update(const WindowState::List &updated,
36                                         const WindowState::List &removed) {
37   std::lock_guard<std::mutex> l(mutex_);
38
39   // Base on the update we get from the Android WindowManagerService we will
40   // create different window instances with the properties supplied. Incoming
41   // layer updates from SurfaceFlinger will be mapped later into those windows
42   // and eventually composited there via GLES (e.g. for popups, ..)
43
44   std::map<Task::Id, WindowState::List> task_updates;
45
46   for (const auto &window : updated) {
47     // Ignore all windows which are not part of the freeform task stack
48     if (window.stack() != Stack::Id::Freeform) continue;
49
50     // And also those which don't have a surface mapped at the moment
51     if (!window.has_surface()) continue;
52
53     // If we know that task already we first collect all window updates
54     // for it so we can apply all of them together.
55     auto w = windows_.find(window.task());
56     if (w != windows_.end()) {
57       auto t = task_updates.find(window.task());
58       if (t == task_updates.end())
59         task_updates.insert({window.task(), {window}});
60       else
61         task_updates[window.task()].push_back(window);
62       continue;
63     }
64
65     auto title = window.package_name();
66     auto app = app_db_->find_by_package(window.package_name());
67     if (app.valid())
68       title = app.name;
69
70     if (auto p = platform_.lock()) {
71       auto w = p->create_window(window.task(), window.frame(), title);
72       if (w) {
73         w->attach();
74         windows_.insert({window.task(), w});
75       } else {
76         // FIXME can we call this here safely or do we need to schedule the removal?
77         remove_task(window.task());
78       }
79     }
80   }
81
82   // Send updates we collected per task down to the corresponding window
83   // so that they can update themself.
84   for (const auto &u : task_updates) {
85     auto w = windows_.find(u.first);
86     if (w == windows_.end()) continue;
87
88     w->second->update_state(u.second);
89   }
90
91   // As final step we process all windows we need to remove as they
92   // got killed on the other side. We need to respect here that we
93   // also get removals for windows which are part of a task which is
94   // still in use by other windows.
95   for (const auto &window : removed) {
96     auto w = windows_.find(window.task());
97     if (w == windows_.end()) continue;
98
99     if (task_updates.find(window.task()) == task_updates.end()) {
100       auto platform_window = w->second;
101       platform_window->release();
102       windows_.erase(w);
103     }
104   }
105 }
106
107 std::shared_ptr<Window> MultiWindowManager::find_window_for_task(const Task::Id &task) {
108   std::lock_guard<std::mutex> l(mutex_);
109   for (const auto &w : windows_) {
110     if (w.second->task() == task) return w.second;
111   }
112   return nullptr;
113 }
114
115 void MultiWindowManager::resize_task(const Task::Id &task, const anbox::graphics::Rect &rect,
116                                       const std::int32_t &resize_mode) {
117   android_api_stub_->resize_task(task, rect, resize_mode);
118 }
119
120 void MultiWindowManager::set_focused_task(const Task::Id &task) {
121   android_api_stub_->set_focused_task(task);
122 }
123
124 void MultiWindowManager::remove_task(const Task::Id &task) {
125   android_api_stub_->remove_task(task);
126 }
127 }  // namespace wm
128 }  // namespace anbox