提交 b7c3f545 编写于 作者: A Adam Barth

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
上级 7870498e
......@@ -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",
],
......
// 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_
// 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);
};
......@@ -7,13 +7,13 @@
namespace blink {
PassRefPtr<View> View::create(const base::Closure& schedulePaintCallback)
PassRefPtr<View> 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<EventCallback> callback)
{
m_schedulePaintCallback.Run();
m_eventCallback = callback;
}
void View::setEventCallback(PassOwnPtr<EventCallback> callback)
void View::setBeginFrameCallback(PassOwnPtr<BeginFrameCallback> 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> 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
......@@ -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<View>, public DartWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
~View() override;
static PassRefPtr<View> create(const base::Closure& schedulePaintCallback);
static PassRefPtr<View> 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<EventCallback> callback);
void schedulePaint();
void setBeginFrameCallback(PassOwnPtr<BeginFrameCallback> callback);
void scheduleFrame();
void setDisplayMetrics(const SkyDisplayMetrics& metrics);
bool handleInputEvent(PassRefPtr<Event> 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<EventCallback> m_eventCallback;
OwnPtr<BeginFrameCallback> m_beginFrameCallback;
RefPtr<Picture> m_picture;
};
......
......@@ -10,5 +10,7 @@ interface View {
attribute Picture picture;
void setEventCallback(EventCallback callback);
void schedulePaint();
void setBeginFrameCallback(BeginFrameCallback callback);
void scheduleFrame();
};
......@@ -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<SkPicture> 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
......@@ -7,6 +7,7 @@
#include <memory>
#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<SkPicture> Paint();
bool HandleInputEvent(const WebInputEvent& event);
private:
explicit SkyView(SkyViewClient* client);
void SchedulePaint();
void ScheduleFrame();
class Data;
......
......@@ -9,7 +9,7 @@ namespace blink {
class SkyViewClient {
public:
virtual void SchedulePaint() = 0;
virtual void ScheduleFrame() = 0;
protected:
virtual ~SkyViewClient();
......
......@@ -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);
}
......@@ -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();
}
......@@ -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<Rende
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 }) {
// the x, y parameters have the top left of the node's box as the origin
RenderBox child = _lastChild;
while (child != null) {
assert(child.parentData is BlockParentData);
if ((x >= 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) {
......
......@@ -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();
}
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册