Improve window/layer handling for less flickering and better window movement
This commit is contained in:
parent
06aacfe4df
commit
53c2fac5d4
16 changed files with 163 additions and 69 deletions
|
|
@ -57,3 +57,8 @@ float Renderable::alpha() const
|
||||||
{
|
{
|
||||||
return alpha_;
|
return alpha_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderable::set_screen_position(const anbox::graphics::Rect &screen_position)
|
||||||
|
{
|
||||||
|
screen_position_ = screen_position;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ public:
|
||||||
glm::mat4 transformation() const;
|
glm::mat4 transformation() const;
|
||||||
float alpha() const;
|
float alpha() const;
|
||||||
|
|
||||||
|
void set_screen_position(const anbox::graphics::Rect &screen_position);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
std::uint32_t buffer_;
|
std::uint32_t buffer_;
|
||||||
|
|
|
||||||
|
|
@ -441,7 +441,7 @@ Renderer::Program::Program(GLuint program_id)
|
||||||
position_attr = s_gles2.glGetAttribLocation(id, "position");
|
position_attr = s_gles2.glGetAttribLocation(id, "position");
|
||||||
texcoord_attr = s_gles2.glGetAttribLocation(id, "texcoord");
|
texcoord_attr = s_gles2.glGetAttribLocation(id, "texcoord");
|
||||||
tex_uniform = s_gles2.glGetUniformLocation(id, "tex");
|
tex_uniform = s_gles2.glGetUniformLocation(id, "tex");
|
||||||
centre_uniform = s_gles2.glGetUniformLocation(id, "centre");
|
center_uniform = s_gles2.glGetUniformLocation(id, "centre");
|
||||||
display_transform_uniform = s_gles2.glGetUniformLocation(id, "display_transform");
|
display_transform_uniform = s_gles2.glGetUniformLocation(id, "display_transform");
|
||||||
transform_uniform = s_gles2.glGetUniformLocation(id, "transform");
|
transform_uniform = s_gles2.glGetUniformLocation(id, "transform");
|
||||||
screen_to_gl_coords_uniform = s_gles2.glGetUniformLocation(id, "screen_to_gl_coords");
|
screen_to_gl_coords_uniform = s_gles2.glGetUniformLocation(id, "screen_to_gl_coords");
|
||||||
|
|
@ -985,10 +985,10 @@ const GLchar* const Renderer::vshader =
|
||||||
"uniform mat4 screen_to_gl_coords;\n"
|
"uniform mat4 screen_to_gl_coords;\n"
|
||||||
"uniform mat4 display_transform;\n"
|
"uniform mat4 display_transform;\n"
|
||||||
"uniform mat4 transform;\n"
|
"uniform mat4 transform;\n"
|
||||||
"uniform vec2 centre;\n"
|
"uniform vec2 center;\n"
|
||||||
"varying vec2 v_texcoord;\n"
|
"varying vec2 v_texcoord;\n"
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" vec4 mid = vec4(centre, 0.0, 0.0);\n"
|
" vec4 mid = vec4(center, 0.0, 0.0);\n"
|
||||||
" vec4 transformed = (transform * (vec4(position, 1.0) - mid)) + mid;\n"
|
" vec4 transformed = (transform * (vec4(position, 1.0) - mid)) + mid;\n"
|
||||||
" gl_Position = display_transform * screen_to_gl_coords * transformed;\n"
|
" gl_Position = display_transform * screen_to_gl_coords * transformed;\n"
|
||||||
" v_texcoord = texcoord;\n"
|
" v_texcoord = texcoord;\n"
|
||||||
|
|
@ -1103,11 +1103,11 @@ void Renderer::draw(RendererWindow *window, const Renderable &renderable, const
|
||||||
s_gles2.glActiveTexture(GL_TEXTURE0);
|
s_gles2.glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
auto const& rect = renderable.screen_position();
|
auto const& rect = renderable.screen_position();
|
||||||
GLfloat centrex = rect.left() +
|
GLfloat centerx = rect.left() +
|
||||||
rect.width() / 2.0f;
|
rect.width() / 2.0f;
|
||||||
GLfloat centrey = rect.top() +
|
GLfloat centery = rect.top() +
|
||||||
rect.height() / 2.0f;
|
rect.height() / 2.0f;
|
||||||
s_gles2.glUniform2f(prog.centre_uniform, centrex, centrey);
|
s_gles2.glUniform2f(prog.center_uniform, centerx, centery);
|
||||||
|
|
||||||
s_gles2.glUniformMatrix4fv(prog.transform_uniform, 1, GL_FALSE,
|
s_gles2.glUniformMatrix4fv(prog.transform_uniform, 1, GL_FALSE,
|
||||||
glm::value_ptr(renderable.transformation()));
|
glm::value_ptr(renderable.transformation()));
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ private:
|
||||||
GLint tex_uniform = -1;
|
GLint tex_uniform = -1;
|
||||||
GLint position_attr = -1;
|
GLint position_attr = -1;
|
||||||
GLint texcoord_attr = -1;
|
GLint texcoord_attr = -1;
|
||||||
GLint centre_uniform = -1;
|
GLint center_uniform = -1;
|
||||||
GLint display_transform_uniform = -1;
|
GLint display_transform_uniform = -1;
|
||||||
GLint transform_uniform = -1;
|
GLint transform_uniform = -1;
|
||||||
GLint screen_to_gl_coords_uniform = -1;
|
GLint screen_to_gl_coords_uniform = -1;
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,45 @@ void LayerComposer::submit_layers(const RenderableList &renderables)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &w : win_layers)
|
for (const auto &w : win_layers)
|
||||||
Renderer::get()->draw(w.first->native_handle(), w.first->state().frame(), w.second);
|
{
|
||||||
|
const auto &window = w.first;
|
||||||
|
const auto &renderables = w.second;
|
||||||
|
RenderableList final_renderables;
|
||||||
|
auto new_window_frame = Rect::Invalid;
|
||||||
|
|
||||||
|
// As we get absolute display coordinates from the Android hwcomposer we
|
||||||
|
// need to recalculate all layer coordinates into relatives ones to the
|
||||||
|
// window they are drawn into.
|
||||||
|
for (auto &r : renderables)
|
||||||
|
{
|
||||||
|
if (new_window_frame == Rect::Invalid)
|
||||||
|
new_window_frame = r.screen_position();
|
||||||
|
else
|
||||||
|
new_window_frame.merge(r.screen_position());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &r : renderables)
|
||||||
|
{
|
||||||
|
auto left = r.screen_position().left() - new_window_frame.left();
|
||||||
|
auto top = r.screen_position().top() - new_window_frame.top();
|
||||||
|
|
||||||
|
auto rect = Rect{
|
||||||
|
left, top,
|
||||||
|
r.screen_position().width() + left,
|
||||||
|
r.screen_position().height() + top,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto new_renderable = r;
|
||||||
|
new_renderable.set_screen_position(rect);
|
||||||
|
final_renderables.push_back(new_renderable);
|
||||||
|
}
|
||||||
|
|
||||||
|
w.first->update_frame(new_window_frame);
|
||||||
|
|
||||||
|
Renderer::get()->draw(window->native_handle(),
|
||||||
|
Rect{0, 0, window->frame().width(), window->frame().height()},
|
||||||
|
final_renderables);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,19 @@
|
||||||
|
|
||||||
#include "anbox/graphics/rect.h"
|
#include "anbox/graphics/rect.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
const Rect Rect::Invalid{-1,-1,-1,-1};
|
const Rect Rect::Invalid{-1,-1,-1,-1};
|
||||||
const Rect Rect::Empty{0,0,0,0};
|
const Rect Rect::Empty{0,0,0,0};
|
||||||
|
|
||||||
|
void Rect::merge(const Rect &rhs)
|
||||||
|
{
|
||||||
|
left_ = std::min(left_, rhs.left());
|
||||||
|
top_ = std::min(top_, rhs.top());
|
||||||
|
right_ = std::max(right_, rhs.right());
|
||||||
|
bottom_ = std::max(bottom_, rhs.bottom());
|
||||||
|
}
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,8 @@ public:
|
||||||
return !operator == (rhs);
|
return !operator == (rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void merge(const Rect &rhs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::int32_t left_;
|
std::int32_t left_;
|
||||||
std::int32_t top_;
|
std::int32_t top_;
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,10 @@
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace ubuntu {
|
namespace ubuntu {
|
||||||
PlatformPolicy::PlatformPolicy(const std::shared_ptr<input::Manager> &input_manager) :
|
PlatformPolicy::PlatformPolicy(const std::shared_ptr<input::Manager> &input_manager,
|
||||||
|
const std::shared_ptr<bridge::AndroidApiStub> &android_api) :
|
||||||
input_manager_(input_manager),
|
input_manager_(input_manager),
|
||||||
|
android_api_(android_api),
|
||||||
event_thread_running_(false) {
|
event_thread_running_(false) {
|
||||||
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0)
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0)
|
||||||
|
|
@ -181,9 +183,9 @@ Window::Id PlatformPolicy::next_window_id() {
|
||||||
return next_id++;
|
return next_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<wm::Window> PlatformPolicy::create_window(const wm::WindowState &state) {
|
std::shared_ptr<wm::Window> PlatformPolicy::create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) {
|
||||||
auto id = next_window_id();
|
auto id = next_window_id();
|
||||||
auto w = std::make_shared<Window>(id, shared_from_this(), state);
|
auto w = std::make_shared<Window>(id, task, shared_from_this(), frame);
|
||||||
windows_.insert({id, w});
|
windows_.insert({id, w});
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ public:
|
||||||
PlatformPolicy(const std::shared_ptr<input::Manager> &input_manager);
|
PlatformPolicy(const std::shared_ptr<input::Manager> &input_manager);
|
||||||
~PlatformPolicy();
|
~PlatformPolicy();
|
||||||
|
|
||||||
std::shared_ptr<wm::Window> create_window(const wm::WindowState &state) override;
|
std::shared_ptr<wm::Window> create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) override;
|
||||||
|
|
||||||
void window_deleted(const Window::Id &id) override;
|
void window_deleted(const Window::Id &id) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,19 +41,20 @@ public:
|
||||||
virtual void window_deleted(const Id &id) = 0;
|
virtual void window_deleted(const Id &id) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Window(const Id &id, const std::shared_ptr<Observer> &observer, const wm::WindowState &state);
|
Window(const Id &id, const wm::Task::Id &task, const std::shared_ptr<Observer> &observer, const graphics::Rect &frame);
|
||||||
Window(int x, int y, int width, int height);
|
Window(int x, int y, int width, int height);
|
||||||
~Window();
|
~Window();
|
||||||
|
|
||||||
void resize(int width, int height);
|
|
||||||
int update_position(int x, int y);
|
|
||||||
|
|
||||||
void process_event(const SDL_Event &event);
|
void process_event(const SDL_Event &event);
|
||||||
|
|
||||||
EGLNativeWindowType native_handle() const override;
|
EGLNativeWindowType native_handle() const override;
|
||||||
Id id() const;
|
Id id() const;
|
||||||
std::uint32_t window_id() const;
|
std::uint32_t window_id() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resize(int width, int height) override;
|
||||||
|
void update_position(int x, int y) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Id id_;
|
Id id_;
|
||||||
std::shared_ptr<Observer> observer_;
|
std::shared_ptr<Observer> observer_;
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,17 @@
|
||||||
namespace {
|
namespace {
|
||||||
class NullWindow : public anbox::wm::Window {
|
class NullWindow : public anbox::wm::Window {
|
||||||
public:
|
public:
|
||||||
NullWindow(const anbox::wm::WindowState &state) :
|
NullWindow(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) :
|
||||||
anbox::wm::Window(state) {
|
anbox::wm::Window(0, frame) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resize(int width, int height) override {
|
||||||
|
WARNING("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_position(int x, int y) override {
|
||||||
|
WARNING("Not implemented");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -33,10 +42,10 @@ namespace wm {
|
||||||
DefaultPlatformPolicy::DefaultPlatformPolicy() {
|
DefaultPlatformPolicy::DefaultPlatformPolicy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Window> DefaultPlatformPolicy::create_window(const WindowState &state)
|
std::shared_ptr<Window> DefaultPlatformPolicy::create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame)
|
||||||
{
|
{
|
||||||
DEBUG("");
|
DEBUG("");
|
||||||
return std::make_shared<::NullWindow>(state);
|
return std::make_shared<::NullWindow>(task, frame);
|
||||||
}
|
}
|
||||||
} // namespace wm
|
} // namespace wm
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace wm {
|
||||||
class DefaultPlatformPolicy : public PlatformPolicy {
|
class DefaultPlatformPolicy : public PlatformPolicy {
|
||||||
public:
|
public:
|
||||||
DefaultPlatformPolicy();
|
DefaultPlatformPolicy();
|
||||||
std::shared_ptr<Window> create_window(const WindowState &state) override;
|
std::shared_ptr<Window> create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) override;
|
||||||
};
|
};
|
||||||
} // namespace wm
|
} // namespace wm
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
|
|
@ -35,40 +35,63 @@ void Manager::apply_window_state_update(const WindowState::List &updated,
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(mutex_);
|
std::lock_guard<std::mutex> l(mutex_);
|
||||||
|
|
||||||
DEBUG("updated %d removed %d", updated.size(), removed.size());
|
|
||||||
|
|
||||||
// Base on the update we get from the Android WindowManagerService we will create
|
// Base on the update we get from the Android WindowManagerService we will create
|
||||||
// different window instances with the properties supplied. Incoming layer updates
|
// different window instances with the properties supplied. Incoming layer updates
|
||||||
// from SurfaceFlinger will be mapped later into those windows and eventually
|
// from SurfaceFlinger will be mapped later into those windows and eventually
|
||||||
// composited there via GLES (e.g. for popups, ..)
|
// composited there via GLES (e.g. for popups, ..)
|
||||||
|
|
||||||
|
std::map<Task::Id, WindowState::List> task_updates;
|
||||||
|
|
||||||
for (const auto &window : updated)
|
for (const auto &window : updated)
|
||||||
{
|
{
|
||||||
|
// Ignore all windows which are not part of the freeform task stack
|
||||||
|
if (window.stack() != Stack::Freeform)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// And also those which don't have a surface mapped at the moment
|
||||||
|
if (!window.has_surface())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 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());
|
auto w = windows_.find(window.task());
|
||||||
if (w != windows_.end())
|
if (w != windows_.end())
|
||||||
{
|
{
|
||||||
w->second->update_state(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);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// HACK: We ignore the first task here which will be always the home
|
|
||||||
// stack of Android. This needs to be solved differently so that the
|
auto platform_window = platform_->create_window(window.task(), window.frame());
|
||||||
// Android side doesn't create this stack at all.
|
|
||||||
if (window.task() == 0)
|
|
||||||
continue;
|
|
||||||
auto platform_window = platform_->create_window(window);
|
|
||||||
platform_window->ref();
|
|
||||||
platform_window->attach();
|
platform_window->attach();
|
||||||
windows_.insert({window.task(), platform_window});
|
windows_.insert({window.task(), platform_window});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
for (const auto &window : removed)
|
||||||
{
|
{
|
||||||
auto w = windows_.find(window.task());
|
auto w = windows_.find(window.task());
|
||||||
if (w == windows_.end())
|
if (w == windows_.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
w->second->unref();
|
if (task_updates.find(window.task()) == task_updates.end())
|
||||||
if (!w->second->still_used())
|
|
||||||
{
|
{
|
||||||
auto platform_window = w->second;
|
auto platform_window = w->second;
|
||||||
platform_window->release();
|
platform_window->release();
|
||||||
|
|
@ -80,10 +103,9 @@ void Manager::apply_window_state_update(const WindowState::List &updated,
|
||||||
std::shared_ptr<Window> Manager::find_window_for_task(const Task::Id &task)
|
std::shared_ptr<Window> Manager::find_window_for_task(const Task::Id &task)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(mutex_);
|
std::lock_guard<std::mutex> l(mutex_);
|
||||||
|
|
||||||
for (const auto &w : windows_)
|
for (const auto &w : windows_)
|
||||||
{
|
{
|
||||||
if (w.second->state().task() == task)
|
if (w.second->task() == task)
|
||||||
return w.second;
|
return w.second;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ class PlatformPolicy {
|
||||||
public:
|
public:
|
||||||
virtual ~PlatformPolicy();
|
virtual ~PlatformPolicy();
|
||||||
|
|
||||||
virtual std::shared_ptr<Window> create_window(const WindowState &state) = 0;
|
virtual std::shared_ptr<Window> create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) = 0;
|
||||||
};
|
};
|
||||||
} // namespace wm
|
} // namespace wm
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
|
|
@ -21,20 +21,38 @@
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace wm {
|
namespace wm {
|
||||||
Window::Window(const WindowState &state) :
|
Window::Window(const Task::Id &task, const graphics::Rect &frame) :
|
||||||
state_(state),
|
task_(task),
|
||||||
refcount_(0) {
|
frame_(frame) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::~Window() {
|
Window::~Window() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::update_state(const WindowState &new_state) {
|
void Window::update_state(const WindowState::List &states)
|
||||||
state_ = new_state;
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowState Window::state() const {
|
void Window::update_frame(const graphics::Rect &frame)
|
||||||
return state_;
|
{
|
||||||
|
if (frame == frame_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (frame.width() != frame_.width() || frame.height() != frame_.height())
|
||||||
|
resize(frame.width(), frame.height());
|
||||||
|
|
||||||
|
if (frame.top() != frame_.top() || frame.left() != frame_.left())
|
||||||
|
update_position(frame.left(), frame.top());
|
||||||
|
|
||||||
|
frame_ = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task::Id Window::task() const {
|
||||||
|
return task_;
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics::Rect Window::frame() const {
|
||||||
|
return frame_;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLNativeWindowType Window::native_handle() const {
|
EGLNativeWindowType Window::native_handle() const {
|
||||||
|
|
@ -48,23 +66,6 @@ bool Window::attach() {
|
||||||
void Window::release() {
|
void Window::release() {
|
||||||
Renderer::get()->destroyNativeWindow(native_handle());
|
Renderer::get()->destroyNativeWindow(native_handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::ref() {
|
|
||||||
refcount_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::unref() {
|
|
||||||
if (refcount_ == 0) {
|
|
||||||
WARNING("reference count is out of sync");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
refcount_--;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Window::still_used() const {
|
|
||||||
return refcount_ > 0;
|
|
||||||
}
|
|
||||||
} // namespace wm
|
} // namespace wm
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,24 +42,26 @@ class Window
|
||||||
public:
|
public:
|
||||||
typedef std::vector<Window> List;
|
typedef std::vector<Window> List;
|
||||||
|
|
||||||
Window(const WindowState &new_state);
|
Window(const Task::Id &task, const graphics::Rect &frame);
|
||||||
virtual ~Window();
|
virtual ~Window();
|
||||||
|
|
||||||
bool attach();
|
bool attach();
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
void ref();
|
void update_state(const WindowState::List &states);
|
||||||
void unref();
|
void update_frame(const graphics::Rect &frame);
|
||||||
bool still_used() const;
|
|
||||||
|
|
||||||
void update_state(const WindowState &state);
|
|
||||||
|
|
||||||
virtual EGLNativeWindowType native_handle() const;
|
virtual EGLNativeWindowType native_handle() const;
|
||||||
WindowState state() const;
|
graphics::Rect frame() const;
|
||||||
|
Task::Id task() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void resize(int width, int height) = 0;
|
||||||
|
virtual void update_position(int x, int y) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WindowState state_;
|
Task::Id task_;
|
||||||
std::uint32_t refcount_;
|
graphics::Rect frame_;
|
||||||
};
|
};
|
||||||
} // namespace wm
|
} // namespace wm
|
||||||
} // namespace anbox
|
} // namespace anbox
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue