| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <unistd.h> |
| 6 |
| 7 #include <string> |
| 8 |
| 9 #include "base/bind.h" |
| 10 #include "base/macros.h" |
| 11 #include "mojo/application/application_runner_chromium.h" |
| 12 #include "mojo/public/c/system/main.h" |
| 13 #include "mojo/ui/choreographer.h" |
| 14 #include "mojo/ui/ganesh_view.h" |
| 15 #include "mojo/ui/input_handler.h" |
| 16 #include "mojo/ui/view_provider_app.h" |
| 17 #include "third_party/dejavu-fonts-ttf-2.34/kDejaVuSansMonoRegular.h" |
| 18 #include "third_party/skia/include/core/SkCanvas.h" |
| 19 #include "third_party/skia/include/core/SkColor.h" |
| 20 #include "third_party/skia/include/core/SkRect.h" |
| 21 #include "third_party/skia/include/core/SkStream.h" |
| 22 #include "third_party/skia/include/core/SkTypeface.h" |
| 23 |
| 24 namespace examples { |
| 25 |
| 26 namespace { |
| 27 constexpr uint32_t kContentImageResourceId = 1; |
| 28 constexpr uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId; |
| 29 |
| 30 enum class Action { |
| 31 kHang10, |
| 32 kStutter30, |
| 33 kCrash, |
| 34 }; |
| 35 |
| 36 struct Button { |
| 37 const char* label; |
| 38 Action action; |
| 39 }; |
| 40 |
| 41 const Button kButtons[] = { |
| 42 {"Hang for 10 seconds", Action::kHang10}, |
| 43 {"Stutter for 30 seconds", Action::kStutter30}, |
| 44 {"Crash!", Action::kCrash}, |
| 45 }; |
| 46 |
| 47 constexpr SkScalar kButtonWidth = 300; |
| 48 constexpr SkScalar kButtonHeight = 30; |
| 49 constexpr SkScalar kMargin = 15; |
| 50 } // namespace |
| 51 |
| 52 class JankView : public mojo::ui::GaneshView, |
| 53 public mojo::ui::ChoreographerDelegate, |
| 54 public mojo::ui::InputListener { |
| 55 public: |
| 56 JankView(mojo::ApplicationImpl* app_impl, |
| 57 mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request) |
| 58 : GaneshView(app_impl, view_owner_request.Pass(), "Jank"), |
| 59 choreographer_(scene(), this), |
| 60 input_handler_(GetViewServiceProvider(), this), |
| 61 typeface_(skia::AdoptRef(SkTypeface::CreateFromStream( |
| 62 new SkMemoryStream(font_data::kDejaVuSansMonoRegular.data, |
| 63 font_data::kDejaVuSansMonoRegular.size)))) {} |
| 64 |
| 65 ~JankView() override {} |
| 66 |
| 67 private: |
| 68 // |GaneshView|: |
| 69 void OnPropertiesChanged( |
| 70 uint32_t old_scene_version, |
| 71 mojo::ui::ViewPropertiesPtr old_properties) override { |
| 72 choreographer_.ScheduleDraw(); |
| 73 } |
| 74 |
| 75 // |InputListener|: |
| 76 void OnEvent(mojo::EventPtr event, const OnEventCallback& callback) override { |
| 77 if (event->pointer_data && event->action == mojo::EventType::POINTER_DOWN) { |
| 78 SkScalar x = event->pointer_data->x; |
| 79 SkScalar y = event->pointer_data->y; |
| 80 if (x >= kMargin && x <= kButtonWidth + kMargin) { |
| 81 int index = (y - kMargin) / (kButtonHeight + kMargin); |
| 82 if (index >= 0 && |
| 83 size_t(index) < sizeof(kButtons) / sizeof(kButtons[0]) && |
| 84 y < (kButtonHeight + kMargin) * (index + 1)) |
| 85 OnClick(kButtons[index]); |
| 86 } |
| 87 } |
| 88 callback.Run(false); |
| 89 } |
| 90 |
| 91 // |ChoreographerDelegate|: |
| 92 void OnDraw(const mojo::gfx::composition::FrameInfo& frame_info, |
| 93 const base::TimeDelta& time_delta) override { |
| 94 if (!properties()) |
| 95 return; |
| 96 |
| 97 auto update = mojo::gfx::composition::SceneUpdate::New(); |
| 98 |
| 99 const mojo::Size& size = *properties()->view_layout->size; |
| 100 if (size.width > 0 && size.height > 0) { |
| 101 mojo::RectF bounds; |
| 102 bounds.width = size.width; |
| 103 bounds.height = size.height; |
| 104 |
| 105 mojo::gfx::composition::ResourcePtr content_resource = |
| 106 ganesh_renderer()->DrawCanvas( |
| 107 size, |
| 108 base::Bind(&JankView::DrawContent, base::Unretained(this), size)); |
| 109 DCHECK(content_resource); |
| 110 update->resources.insert(kContentImageResourceId, |
| 111 content_resource.Pass()); |
| 112 |
| 113 auto root_node = mojo::gfx::composition::Node::New(); |
| 114 root_node->hit_test_behavior = |
| 115 mojo::gfx::composition::HitTestBehavior::New(); |
| 116 root_node->op = mojo::gfx::composition::NodeOp::New(); |
| 117 root_node->op->set_image(mojo::gfx::composition::ImageNodeOp::New()); |
| 118 root_node->op->get_image()->content_rect = bounds.Clone(); |
| 119 root_node->op->get_image()->image_resource_id = kContentImageResourceId; |
| 120 update->nodes.insert(kRootNodeId, root_node.Pass()); |
| 121 } else { |
| 122 auto root_node = mojo::gfx::composition::Node::New(); |
| 123 update->nodes.insert(kRootNodeId, root_node.Pass()); |
| 124 } |
| 125 |
| 126 scene()->Update(update.Pass()); |
| 127 |
| 128 auto metadata = mojo::gfx::composition::SceneMetadata::New(); |
| 129 metadata->version = scene_version(); |
| 130 scene()->Publish(metadata.Pass()); |
| 131 |
| 132 choreographer_.ScheduleDraw(); |
| 133 |
| 134 if (MojoGetTimeTicksNow() < stutter_end_time_) |
| 135 sleep(2); |
| 136 } |
| 137 |
| 138 void DrawContent(const mojo::Size& size, SkCanvas* canvas) { |
| 139 SkScalar hsv[3] = {fmod(MojoGetTimeTicksNow() * 0.000001f * 60, 360.f), 1, |
| 140 1}; |
| 141 canvas->clear(SkHSVToColor(hsv)); |
| 142 |
| 143 SkScalar x = kMargin; |
| 144 SkScalar y = kMargin; |
| 145 for (const auto& button : kButtons) { |
| 146 DrawButton(canvas, button.label, |
| 147 SkRect::MakeXYWH(x, y, kButtonWidth, kButtonHeight)); |
| 148 y += kButtonHeight + kMargin; |
| 149 } |
| 150 } |
| 151 |
| 152 void DrawButton(SkCanvas* canvas, const char* label, const SkRect& bounds) { |
| 153 SkPaint boxPaint; |
| 154 boxPaint.setColor(SkColorSetRGB(200, 200, 200)); |
| 155 canvas->drawRect(bounds, boxPaint); |
| 156 boxPaint.setColor(SkColorSetRGB(40, 40, 40)); |
| 157 boxPaint.setStyle(SkPaint::kStroke_Style); |
| 158 canvas->drawRect(bounds, boxPaint); |
| 159 |
| 160 SkPaint textPaint; |
| 161 textPaint.setColor(SK_ColorBLACK); |
| 162 textPaint.setTextSize(16); |
| 163 textPaint.setTextEncoding(SkPaint::kUTF8_TextEncoding); |
| 164 textPaint.setTypeface(typeface_.get()); |
| 165 textPaint.setAntiAlias(true); |
| 166 SkRect textBounds; |
| 167 textPaint.measureText(label, strlen(label), &textBounds); |
| 168 canvas->drawText(label, strlen(label), |
| 169 bounds.centerX() - textBounds.centerX(), |
| 170 bounds.centerY() - textBounds.centerY(), textPaint); |
| 171 } |
| 172 |
| 173 void OnClick(const Button& button) { |
| 174 LOG(INFO) << "Clicked: " << button.label; |
| 175 |
| 176 switch (button.action) { |
| 177 case Action::kHang10: { |
| 178 sleep(10); |
| 179 break; |
| 180 } |
| 181 |
| 182 case Action::kStutter30: { |
| 183 stutter_end_time_ = MojoGetTimeTicksNow() + 30 * 1000000; |
| 184 break; |
| 185 } |
| 186 |
| 187 case Action::kCrash: { |
| 188 abort(); |
| 189 break; |
| 190 } |
| 191 } |
| 192 } |
| 193 |
| 194 mojo::ui::Choreographer choreographer_; |
| 195 mojo::ui::InputHandler input_handler_; |
| 196 skia::RefPtr<SkTypeface> typeface_; |
| 197 int64_t stutter_end_time_ = 0u; |
| 198 |
| 199 DISALLOW_COPY_AND_ASSIGN(JankView); |
| 200 }; |
| 201 |
| 202 class JankApp : public mojo::ui::ViewProviderApp { |
| 203 public: |
| 204 JankApp() {} |
| 205 ~JankApp() override {} |
| 206 |
| 207 void CreateView( |
| 208 const std::string& connection_url, |
| 209 mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request, |
| 210 mojo::InterfaceRequest<mojo::ServiceProvider> services, |
| 211 mojo::InterfaceHandle<mojo::ServiceProvider> exposed_services) override { |
| 212 new JankView(app_impl(), view_owner_request.Pass()); |
| 213 } |
| 214 |
| 215 private: |
| 216 DISALLOW_COPY_AND_ASSIGN(JankApp); |
| 217 }; |
| 218 |
| 219 } // namespace examples |
| 220 |
| 221 MojoResult MojoMain(MojoHandle application_request) { |
| 222 mojo::ApplicationRunnerChromium runner(new examples::JankApp()); |
| 223 return runner.Run(application_request); |
| 224 } |
| OLD | NEW |