From b7c3f545f056978b51be9ecb488c3e2153d5241f Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 21 May 2015 11:22:17 -0700 Subject: [PATCH] Make hit testing work in layout2.dart This CL makes simple_render_tree.dart interactive by making the hit testing system work. I've also added a mechanism for requesting an animation frame. R=eseidel@chromium.org, ianh@google.com Review URL: https://codereview.chromium.org/1153543002 --- engine/core/core.gni | 3 ++ engine/core/view/BeginFrameCallback.h | 18 +++++++++ engine/core/view/BeginFrameCallback.idl | 7 ++++ engine/core/view/View.cpp | 29 ++++++++++---- engine/core/view/View.h | 13 ++++-- engine/core/view/View.idl | 4 +- engine/public/sky/sky_view.cc | 10 +++-- engine/public/sky/sky_view.h | 5 ++- engine/public/sky/sky_view_client.h | 2 +- examples/raw/hello_world.dart | 6 +-- examples/raw/simple_render_tree.dart | 41 +++++++++++++++++-- sdk/lib/framework/layout2.dart | 53 +++++++++++++++++-------- shell/ui/engine.cc | 5 ++- shell/ui/engine.h | 2 +- 14 files changed, 156 insertions(+), 42 deletions(-) create mode 100644 engine/core/view/BeginFrameCallback.h create mode 100644 engine/core/view/BeginFrameCallback.idl diff --git a/engine/core/core.gni b/engine/core/core.gni index bde5e29a62..1e82014973 100644 --- a/engine/core/core.gni +++ b/engine/core/core.gni @@ -1028,6 +1028,8 @@ sky_core_files = [ "script/dom_dart_state.cc", "script/dom_dart_state.h", "script/monitor.h", + "view/BeginFrameCallback.h", + "view/EventCallback.h", "view/View.cpp", "view/View.h", ] @@ -1111,6 +1113,7 @@ core_idl_files = get_path_info([ "painting/PaintingContext.idl", "painting/Picture.idl", "painting/PictureRecorder.idl", + "view/BeginFrameCallback.idl", "view/EventCallback.idl", "view/View.idl", ], diff --git a/engine/core/view/BeginFrameCallback.h b/engine/core/view/BeginFrameCallback.h new file mode 100644 index 0000000000..8b1faee124 --- /dev/null +++ b/engine/core/view/BeginFrameCallback.h @@ -0,0 +1,18 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_CORE_VIEW_BEGINFRAMECALLBACK_H_ +#define SKY_ENGINE_CORE_VIEW_BEGINFRAMECALLBACK_H_ + +namespace blink { + +class BeginFrameCallback { +public: + virtual ~BeginFrameCallback() { } + virtual bool handleEvent(double highResTime) = 0; +}; + +} + +#endif // SKY_ENGINE_CORE_VIEW_BEGINFRAMECALLBACK_H_ diff --git a/engine/core/view/BeginFrameCallback.idl b/engine/core/view/BeginFrameCallback.idl new file mode 100644 index 0000000000..eb8b9aebea --- /dev/null +++ b/engine/core/view/BeginFrameCallback.idl @@ -0,0 +1,7 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +callback interface BeginFrameCallback { + boolean handleEvent(double highResTime); +}; diff --git a/engine/core/view/View.cpp b/engine/core/view/View.cpp index b885139795..cc1a152f93 100644 --- a/engine/core/view/View.cpp +++ b/engine/core/view/View.cpp @@ -7,13 +7,13 @@ namespace blink { -PassRefPtr View::create(const base::Closure& schedulePaintCallback) +PassRefPtr View::create(const base::Closure& scheduleFrameCallback) { - return adoptRef(new View(schedulePaintCallback)); + return adoptRef(new View(scheduleFrameCallback)); } -View::View(const base::Closure& schedulePaintCallback) - : m_schedulePaintCallback(schedulePaintCallback) +View::View(const base::Closure& scheduleFrameCallback) + : m_scheduleFrameCallback(scheduleFrameCallback) { } @@ -33,14 +33,19 @@ double View::height() const return h / m_displayMetrics.device_pixel_ratio; } -void View::schedulePaint() +void View::setEventCallback(PassOwnPtr callback) { - m_schedulePaintCallback.Run(); + m_eventCallback = callback; } -void View::setEventCallback(PassOwnPtr callback) +void View::setBeginFrameCallback(PassOwnPtr callback) { - m_eventCallback = callback; + m_beginFrameCallback = callback; +} + +void View::scheduleFrame() +{ + m_scheduleFrameCallback.Run(); } void View::setDisplayMetrics(const SkyDisplayMetrics& metrics) @@ -53,4 +58,12 @@ bool View::handleInputEvent(PassRefPtr event) return m_eventCallback && m_eventCallback->handleEvent(event.get()); } +void View::beginFrame(base::TimeTicks frameTime) +{ + if (!m_beginFrameCallback) + return; + double frameTimeMS = (frameTime - base::TimeTicks()).InMillisecondsF(); + m_beginFrameCallback->handleEvent(frameTimeMS); +} + } // namespace blink diff --git a/engine/core/view/View.h b/engine/core/view/View.h index edb3d567be..e06c02618c 100644 --- a/engine/core/view/View.h +++ b/engine/core/view/View.h @@ -6,7 +6,9 @@ #define SKY_ENGINE_CORE_VIEW_VIEW_H_ #include "base/callback.h" +#include "base/time/time.h" #include "sky/engine/core/painting/Picture.h" +#include "sky/engine/core/view/BeginFrameCallback.h" #include "sky/engine/core/view/EventCallback.h" #include "sky/engine/public/platform/sky_display_metrics.h" #include "sky/engine/tonic/dart_wrappable.h" @@ -19,7 +21,7 @@ class View : public RefCounted, public DartWrappable { DEFINE_WRAPPERTYPEINFO(); public: ~View() override; - static PassRefPtr create(const base::Closure& schedulePaintCallback); + static PassRefPtr create(const base::Closure& scheduleFrameCallback); double devicePixelRatio() const { return m_displayMetrics.device_pixel_ratio; } double width() const; @@ -30,17 +32,20 @@ public: void setEventCallback(PassOwnPtr callback); - void schedulePaint(); + void setBeginFrameCallback(PassOwnPtr callback); + void scheduleFrame(); void setDisplayMetrics(const SkyDisplayMetrics& metrics); bool handleInputEvent(PassRefPtr event); + void beginFrame(base::TimeTicks frameTime); private: - explicit View(const base::Closure& schedulePaintCallback); + explicit View(const base::Closure& scheduleFrameCallback); - base::Closure m_schedulePaintCallback; + base::Closure m_scheduleFrameCallback; SkyDisplayMetrics m_displayMetrics; OwnPtr m_eventCallback; + OwnPtr m_beginFrameCallback; RefPtr m_picture; }; diff --git a/engine/core/view/View.idl b/engine/core/view/View.idl index 3bdccddcb3..b9b25cbb7c 100644 --- a/engine/core/view/View.idl +++ b/engine/core/view/View.idl @@ -10,5 +10,7 @@ interface View { attribute Picture picture; void setEventCallback(EventCallback callback); - void schedulePaint(); + + void setBeginFrameCallback(BeginFrameCallback callback); + void scheduleFrame(); }; diff --git a/engine/public/sky/sky_view.cc b/engine/public/sky/sky_view.cc index b057cc4114..01cbac27ac 100644 --- a/engine/public/sky/sky_view.cc +++ b/engine/public/sky/sky_view.cc @@ -49,7 +49,7 @@ void SkyView::SetDisplayMetrics(const SkyDisplayMetrics& metrics) { void SkyView::Load(const WebURL& url) { data_->view_ = View::create(base::Bind( - &SkyView::SchedulePaint, weak_factory_.GetWeakPtr())); + &SkyView::ScheduleFrame, weak_factory_.GetWeakPtr())); data_->view_->setDisplayMetrics(display_metrics_); dart_controller_.reset(new DartController); @@ -58,6 +58,10 @@ void SkyView::Load(const WebURL& url) { dart_controller_->LoadMainLibrary(url); } +void SkyView::BeginFrame(base::TimeTicks frame_time) { + data_->view_->beginFrame(frame_time); +} + skia::RefPtr SkyView::Paint() { if (Picture* picture = data_->view_->picture()) return skia::SharePtr(picture->toSkia()); @@ -90,8 +94,8 @@ bool SkyView::HandleInputEvent(const WebInputEvent& inputEvent) { return false; } -void SkyView::SchedulePaint() { - client_->SchedulePaint(); +void SkyView::ScheduleFrame() { + client_->ScheduleFrame(); } } // namespace blink diff --git a/engine/public/sky/sky_view.h b/engine/public/sky/sky_view.h index 1e9e00a39e..e8847d797a 100644 --- a/engine/public/sky/sky_view.h +++ b/engine/public/sky/sky_view.h @@ -7,6 +7,7 @@ #include #include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "skia/ext/refptr.h" #include "sky/engine/public/platform/WebCommon.h" #include "sky/engine/public/platform/WebURL.h" @@ -25,13 +26,15 @@ class SkyView { void SetDisplayMetrics(const SkyDisplayMetrics& metrics); void Load(const WebURL& url); + + void BeginFrame(base::TimeTicks frame_time); skia::RefPtr Paint(); bool HandleInputEvent(const WebInputEvent& event); private: explicit SkyView(SkyViewClient* client); - void SchedulePaint(); + void ScheduleFrame(); class Data; diff --git a/engine/public/sky/sky_view_client.h b/engine/public/sky/sky_view_client.h index 16f9552b4d..54ab8262e3 100644 --- a/engine/public/sky/sky_view_client.h +++ b/engine/public/sky/sky_view_client.h @@ -9,7 +9,7 @@ namespace blink { class SkyViewClient { public: - virtual void SchedulePaint() = 0; + virtual void ScheduleFrame() = 0; protected: virtual ~SkyViewClient(); diff --git a/examples/raw/hello_world.dart b/examples/raw/hello_world.dart index b27b29da7a..61079b5927 100644 --- a/examples/raw/hello_world.dart +++ b/examples/raw/hello_world.dart @@ -20,13 +20,13 @@ Picture draw(int a, int r, int g, int b) { bool handleEvent(Event event) { if (event.type == "pointerdown") { view.picture = draw(255, 0, 0, 255); - view.schedulePaint(); + view.scheduleFrame(); return true; } if (event.type == "pointerup") { view.picture = draw(255, 0, 255, 0); - view.schedulePaint(); + view.scheduleFrame(); return true; } @@ -36,7 +36,7 @@ bool handleEvent(Event event) { void main() { print("Hello, world"); view.picture = draw(255, 0, 255, 0); - view.schedulePaint(); + view.scheduleFrame(); view.setEventCallback(handleEvent); } diff --git a/examples/raw/simple_render_tree.dart b/examples/raw/simple_render_tree.dart index ee168f5609..205043523b 100644 --- a/examples/raw/simple_render_tree.dart +++ b/examples/raw/simple_render_tree.dart @@ -7,8 +7,11 @@ import 'dart:sky'; import 'package:sky/framework/layout2.dart'; class RenderSolidColor extends RenderDecoratedBox { + final int backgroundColor; + RenderSolidColor(int backgroundColor) - : super(new BoxDecoration(backgroundColor: backgroundColor)); + : super(new BoxDecoration(backgroundColor: backgroundColor)), + backgroundColor = backgroundColor; BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { return new BoxDimensions.withConstraints(constraints, height: 200.0); @@ -19,16 +22,48 @@ class RenderSolidColor extends RenderDecoratedBox { setHeight(constraints, 200.0); layoutDone(); } + + bool handlePointer(PointerEvent event, { double x: 0.0, double y: 0.0 }) { + if (event.type == 'pointerdown') { + setBoxDecoration(new BoxDecoration(backgroundColor: 0xFFFF0000)); + return true; + } + + if (event.type == 'pointerup') { + setBoxDecoration(new BoxDecoration(backgroundColor: backgroundColor)); + return true; + } + + return false; + } +} + +RenderView renderView; + +void beginFrame(double timeStamp) { + RenderNode.flushLayout(); + + renderView.paintFrame(); +} + +bool handleEvent(Event event) { + if (event is! PointerEvent) + return false; + return renderView.handlePointer(event, x: event.x, y: event.y); } void main() { + view.setEventCallback(handleEvent); + view.setBeginFrameCallback(beginFrame); + var root = new RenderBlock( decoration: new BoxDecoration(backgroundColor: 0xFF00FFFF)); root.add(new RenderSolidColor(0xFF00FF00)); root.add(new RenderSolidColor(0xFF0000FF)); - RenderView renderView = new RenderView(root: root); + renderView = new RenderView(root: root); renderView.layout(newWidth: view.width, newHeight: view.height); - renderView.paintFrame(); + + view.scheduleFrame(); } diff --git a/sdk/lib/framework/layout2.dart b/sdk/lib/framework/layout2.dart index c3ae7d70c0..75ff4e6878 100644 --- a/sdk/lib/framework/layout2.dart +++ b/sdk/lib/framework/layout2.dart @@ -218,7 +218,7 @@ abstract class RenderNode extends AbstractNode { // HIT TESTING - void handlePointer(sky.PointerEvent event) { + bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) { // override this if you have children, to hand it to the appropriate child // override this if you want to do anything with the pointer event } @@ -229,6 +229,10 @@ abstract class RenderNode extends AbstractNode { static bool _debugDoingPaint = false; void markNeedsPaint() { assert(!_debugDoingPaint); + // TODO(abarth): It's very redunant to call this for every node in the + // render tree during layout. We should instead compute a summary bit and + // call it once at the end of layout. + sky.view.scheduleFrame(); } void paint(RenderNodeDisplayList canvas) { } @@ -468,19 +472,26 @@ class BoxDecoration { } class RenderDecoratedBox extends RenderBox { - BoxDecoration decoration; + BoxDecoration _decoration; - RenderDecoratedBox(this.decoration); + RenderDecoratedBox(BoxDecoration decoration) : _decoration = decoration; + + void setBoxDecoration(BoxDecoration decoration) { + if (_decoration == decoration) + return; + _decoration = decoration; + markNeedsPaint(); + } void paint(RenderNodeDisplayList canvas) { assert(width != null); assert(height != null); - if (decoration == null) + if (_decoration == null) return; - if (decoration.backgroundColor != null) { - sky.Paint paint = new sky.Paint()..color = decoration.backgroundColor; + if (_decoration.backgroundColor != null) { + sky.Paint paint = new sky.Paint()..color = _decoration.backgroundColor; canvas.drawRect(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint); } } @@ -547,6 +558,12 @@ class RenderView extends RenderNode { assert(false); // nobody tells the screen to rotate, the whole rotate() dance is started from our layout() } + bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) { + if (x < 0.0 || x >= root.width || y < 0.0 || y >= root.height) + return false; + return root.handlePointer(event, x: x, y: y); + } + void paint(RenderNodeDisplayList canvas) { canvas.paintChild(root, 0.0, 0.0); } @@ -556,7 +573,6 @@ class RenderView extends RenderNode { var canvas = new RenderNodeDisplayList(sky.view.width, sky.view.height); paint(canvas); sky.view.picture = canvas.endRecording(); - sky.view.schedulePaint(); RenderNode._debugDoingPaint = false; } @@ -669,19 +685,20 @@ class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin= child.parentData.x) && (x < child.parentData.x + child.width) && (y >= child.parentData.y) && (y < child.parentData.y + child.height)) { - child.handlePointer(event, x: x-child.parentData.x, y: y-child.parentData.y); + if (child.handlePointer(event, x: x-child.parentData.x, y: y-child.parentData.y)) + return true; break; } child = child.parentData.previousSibling; } - super.handlePointer(event); + return super.handlePointer(event, x: x, y: y); } void paint(RenderNodeDisplayList canvas) { @@ -756,17 +773,21 @@ class ScaffoldBox extends RenderBox { layoutDone(); } - void handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) { + bool handlePointer(sky.PointerEvent event, { double x: 0.0, double y: 0.0 }) { if ((drawer != null) && (x < drawer.width)) { - drawer.handlePointer(event, x: x, y: y); + if (drawer.handlePointer(event, x: x, y: y)) + return true; } else if ((toolbar != null) && (y < toolbar.height)) { - toolbar.handlePointer(event, x: x, y: y); + if (toolbar.handlePointer(event, x: x, y: y)) + return true; } else if ((statusbar != null) && (y > (statusbar.parentData as BoxParentData).y)) { - statusbar.handlePointer(event, x: x, y: y-(statusbar.parentData as BoxParentData).y); + if (statusbar.handlePointer(event, x: x, y: y-(statusbar.parentData as BoxParentData).y)) + return true; } else { - body.handlePointer(event, x: x, y: y-(body.parentData as BoxParentData).y); + if (body.handlePointer(event, x: x, y: y-(body.parentData as BoxParentData).y)) + return true; } - super.handlePointer(event, x: x, y: y); + return super.handlePointer(event, x: x, y: y); } void paint(RenderNodeDisplayList canvas) { diff --git a/shell/ui/engine.cc b/shell/ui/engine.cc index 67abfb3202..b16d44e673 100644 --- a/shell/ui/engine.cc +++ b/shell/ui/engine.cc @@ -72,6 +72,9 @@ void Engine::BeginFrame(base::TimeTicks frame_time) { double interval_sec = 1.0 / 60; blink::WebBeginFrameArgs args(frame_time_sec, deadline_sec, interval_sec); + if (sky_view_) + sky_view_->BeginFrame(frame_time); + if (web_view_) { web_view_->beginFrame(args); web_view_->layout(); @@ -203,7 +206,7 @@ void Engine::didCreateIsolate(blink::WebLocalFrame* frame, CreateServiceProvider(config_.service_provider_context)); } -void Engine::SchedulePaint() { +void Engine::ScheduleFrame() { animator_->RequestFrame(); } diff --git a/shell/ui/engine.h b/shell/ui/engine.h index 5311229d75..680179ac82 100644 --- a/shell/ui/engine.h +++ b/shell/ui/engine.h @@ -78,7 +78,7 @@ class Engine : public UIDelegate, Dart_Isolate isolate) override; // SkyViewClient methods: - void SchedulePaint() override; + void ScheduleFrame() override; // Services methods: mojo::NavigatorHost* NavigatorHost() override; -- GitLab