Index: services/ui/public/cpp/window.cc |
diff --git a/services/ui/public/cpp/window.cc b/services/ui/public/cpp/window.cc |
index 81f07e148d87aba1b4f5beadab8273de636d86c7..dd331bb011f4ed64d068caa932a19c94b0e9c8e3 100644 |
--- a/services/ui/public/cpp/window.cc |
+++ b/services/ui/public/cpp/window.cc |
@@ -11,7 +11,13 @@ |
#include <string> |
#include "base/bind.h" |
+#include "base/containers/adapters.h" |
#include "base/macros.h" |
+#include "cc/output/compositor_frame.h" |
+#include "cc/quads/render_pass.h" |
+#include "cc/quads/render_pass_draw_quad.h" |
+#include "cc/quads/shared_quad_state.h" |
+#include "cc/quads/surface_draw_quad.h" |
#include "services/ui/common/transient_window_utils.h" |
#include "services/ui/public/cpp/property_type_converters.h" |
#include "services/ui/public/cpp/window_observer.h" |
@@ -515,10 +521,20 @@ std::string Window::GetName() const { |
//////////////////////////////////////////////////////////////////////////////// |
// Window, protected: |
-Window::Window() : Window(nullptr, static_cast<Id>(-1)) {} |
+Window::Window(bool container) |
+ : Window(nullptr, static_cast<Id>(-1), container) {} |
Window::~Window() { |
FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowDestroying(this)); |
+ if (!surface_info_.surface_id.is_null()) { |
+ // If the existing surface ID is non-null, then we should return the |
+ // existing SurfaceSequence. |
+ if (client_) { |
+ client_->SatisfySurfaceSequence( |
+ server_id_, surface_info_.surface_sequence); |
+ } |
+ } |
+ |
if (client_) |
client_->OnWindowDestroying(this); |
@@ -572,8 +588,9 @@ Window::~Window() { |
//////////////////////////////////////////////////////////////////////////////// |
// Window, private: |
-Window::Window(WindowTreeClient* client, Id id) |
+Window::Window(WindowTreeClient* client, Id id, bool container) |
: client_(client), |
+ container_(container), |
server_id_(id), |
parent_(nullptr), |
stacking_target_(nullptr), |
@@ -586,7 +603,79 @@ Window::Window(WindowTreeClient* client, Id id) |
opacity_(1.0f), |
display_id_(display::Display::kInvalidDisplayID), |
cursor_id_(mojom::Cursor::CURSOR_NULL), |
- parent_drawn_(false) {} |
+ parent_drawn_(false), |
+ draw_timer_(false, false), |
+ weak_factory_(this) { |
+ if (container) { |
+ WantToDraw(); |
+ } |
+} |
+ |
+void Window::WantToDraw() { |
+ if (draw_timer_.IsRunning()) |
+ return; |
+ |
+ // TODO(rjkroege): Use vblank to kick off Draw. |
+ draw_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(16), |
+ base::Bind(&Window::Draw, weak_factory_.GetWeakPtr())); |
+} |
+ |
+void Window::Draw() { |
+ if (!visible_) |
+ return; |
+ |
+ const cc::RenderPassId render_pass_id(1, 1); |
+ std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create(); |
+ render_pass->SetNew(render_pass_id, bounds_, bounds_, gfx::Transform()); |
+ |
+ uint32_t children_drawn = 0; |
+ for (Window* child : base::Reversed(children_)) { |
+ if (child->surface_info_.surface_id.is_null()) |
+ continue; |
+ children_drawn++; |
+ gfx::Transform quad_to_target_transform; |
+ quad_to_target_transform.Translate(child->bounds().x(), |
+ child->bounds().y()); |
+ cc::SharedQuadState* sqs = render_pass->CreateAndAppendSharedQuadState(); |
+ const gfx::Rect bounds_at_origin(child->bounds().size()); |
+ // TODO(fsamuel): These clipping and visible rects are incorrect. They need |
+ // to be populated from CompositorFrame structs. |
+ sqs->SetAll(quad_to_target_transform, |
+ bounds_at_origin.size() /* layer_bounds */, |
+ bounds_at_origin /* visible_layer_bounds */, |
+ bounds_at_origin /* clip_rect */, false /* is_clipped */, |
+ 1.f /* opacity */, SkXfermode::kSrcOver_Mode, |
+ 0 /* sorting-context_id */); |
+ auto* quad = render_pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); |
+ quad->SetAll(sqs, child->bounds() /* rect */, gfx::Rect() /* opaque_rect */, |
+ bounds_at_origin /* visible_rect */, true /* needs_blending*/, |
+ child->surface_info_.surface_id); |
+ } |
+ if (children_drawn) { |
+ std::unique_ptr<cc::DelegatedFrameData> frame_data( |
+ new cc::DelegatedFrameData); |
+ frame_data->render_pass_list.push_back(std::move(render_pass)); |
+ cc::CompositorFrame frame; |
+ frame.delegated_frame_data = std::move(frame_data); |
+ if (!container_surface_) { |
+ SetSharedProperty<bool>( |
+ ui::mojom::WindowManager::kContainer_Property, true); |
+ container_surface_ = RequestSurface(mojom::SurfaceType::DEFAULT); |
+ container_surface_->BindToThread(); |
+ } |
+ container_surface_->SubmitCompositorFrame( |
+ std::move(frame), base::Bind(&base::DoNothing)); |
+ } |
+ |
+ WantToDraw(); |
+} |
+ |
+void Window::SetIsContainer() { |
+ if (!container_) { |
+ container_ = true; |
+ WantToDraw(); |
+ } |
+} |
void Window::SetSharedPropertyInternal(const std::string& name, |
const std::vector<uint8_t>* value) { |
@@ -694,6 +783,28 @@ void Window::LocalSetBounds(const gfx::Rect& old_bounds, |
bounds_ = new_bounds; |
} |
+void Window::LocalSetSurfaceId(const gfx::Size& size, |
+ float device_scale_factor, |
+ const cc::SurfaceId& surface_id, |
+ const cc::SurfaceSequence& surface_sequence) { |
+ const cc::SurfaceId& existing_surface_id = surface_info_.surface_id; |
+ if (!existing_surface_id.is_null() && existing_surface_id != surface_id) { |
+ // If the existing surface ID is non-null, then we should return the |
+ // existing SurfaceSequence. |
+ if (client_) { |
+ client_->SatisfySurfaceSequence( |
+ server_id_, surface_info_.surface_sequence); |
+ } |
+ } |
+ surface_info_ = {size, device_scale_factor, surface_id, surface_sequence}; |
+ if (parent_) { |
+ FOR_EACH_OBSERVER( |
+ WindowObserver, observers_, |
+ OnChildWindowSurfaceCreated(this, size, device_scale_factor, surface_id, |
+ surface_sequence)); |
+ } |
+} |
+ |
void Window::LocalSetClientArea( |
const gfx::Insets& new_client_area, |
const std::vector<gfx::Rect>& additional_client_areas) { |