1// Copyright 2014 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 6// This plugin is intended to be used in a telemetry test for tracing touch 7// input latency. It is a simple touch drawing app, that for each touch move 8// event, it draws a square with fix size. 9// When the plugin instance is initialized, we call 10// InputEventPrivate::StartTrackingLatency to enable latency tracking. 11// And for each touch move event, we call 12// InputEventPrivate::TraceInputLatency(true) to indicate the touch event 13// causes rendering effect and its input latency should be tracked. 14// The plugin is built as a pexe and bundled with a telemetry test page. 15// For how to build the pexe, see the accompanying README file. 16 17#include <algorithm> 18 19#include "ppapi/c/pp_input_event.h" 20#include "ppapi/cpp/graphics_2d.h" 21#include "ppapi/cpp/image_data.h" 22#include "ppapi/cpp/input_event.h" 23#include "ppapi/cpp/instance.h" 24#include "ppapi/cpp/module.h" 25#include "ppapi/cpp/private/input_event_private.h" 26#include "ppapi/cpp/size.h" 27#include "ppapi/cpp/view.h" 28#include "ppapi/utility/graphics/paint_manager.h" 29 30pp::Rect SquareForTouchPoint(int x, int y) { 31 return PP_MakeRectFromXYWH(x - 30, y - 30, 32 30 * 2 + 1, 30 * 2 + 1); 33} 34 35static void FillRect(pp::ImageData* image, 36 int left, 37 int top, 38 int width, 39 int height, 40 uint32_t color) { 41 for (int y = std::max(0, top); 42 y < std::min(image->size().height() - 1, top + height); 43 y++) { 44 for (int x = std::max(0, left); 45 x < std::min(image->size().width() - 1, left + width); 46 x++) { 47 *image->GetAddr32(pp::Point(x, y)) = color; 48 } 49 } 50} 51 52class MyInstance : public pp::Instance, public pp::PaintManager::Client { 53 public: 54 explicit MyInstance(PP_Instance instance) 55 : pp::Instance(instance), 56 paint_manager_() { 57 paint_manager_.Initialize(this, this, false); 58 RequestInputEvents(PP_INPUTEVENT_CLASS_TOUCH); 59 pp::InputEventPrivate::StartTrackingLatency(pp::InstanceHandle(instance)); 60 } 61 62 virtual bool HandleInputEvent(const pp::InputEvent& event) { 63 switch (event.GetType()) { 64 case PP_INPUTEVENT_TYPE_TOUCHSTART: 65 case PP_INPUTEVENT_TYPE_TOUCHEND: 66 case PP_INPUTEVENT_TYPE_TOUCHCANCEL: { 67 pp::InputEventPrivate private_event(event); 68 private_event.TraceInputLatency(false); 69 return true; 70 } 71 72 case PP_INPUTEVENT_TYPE_TOUCHMOVE: { 73 pp::TouchInputEvent touch(event); 74 uint32_t count = touch.GetTouchCount(PP_TOUCHLIST_TYPE_CHANGEDTOUCHES); 75 if (count > 0) { 76 pp::TouchPoint point = touch.GetTouchByIndex( 77 PP_TOUCHLIST_TYPE_CHANGEDTOUCHES, 0); 78 UpdateSquareTouch(static_cast<int>(point.position().x()), 79 static_cast<int>(point.position().y())); 80 pp::InputEventPrivate private_event(event); 81 private_event.TraceInputLatency(true); 82 } else { 83 pp::InputEventPrivate private_event(event); 84 private_event.TraceInputLatency(false); 85 } 86 return true; 87 } 88 default: 89 return false; 90 } 91 } 92 93 virtual void DidChangeView(const pp::View& view) { 94 paint_manager_.SetSize(view.GetRect().size()); 95 } 96 97 // PaintManager::Client implementation. 98 virtual bool OnPaint(pp::Graphics2D& graphics_2d, 99 const std::vector<pp::Rect>& paint_rects, 100 const pp::Rect& paint_bounds) { 101 pp::ImageData updated_image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, 102 paint_bounds.size(), false); 103 104 for (size_t i = 0; i < paint_rects.size(); i++) { 105 // Since our image is just the invalid region, we need to offset the 106 // areas we paint by that much. This is just a light blue background. 107 FillRect(&updated_image, 108 paint_rects[i].x(), 109 paint_rects[i].y(), 110 paint_rects[i].width(), 111 paint_rects[i].height(), 112 0xFF000000); 113 } 114 115 graphics_2d.PaintImageData(updated_image, paint_bounds.point()); 116 return true; 117 } 118 119 private: 120 void UpdateSquareTouch(int x, int y) { 121 paint_manager_.InvalidateRect(SquareForTouchPoint(x, y)); 122 } 123 124 pp::PaintManager paint_manager_; 125}; 126 127class MyModule : public pp::Module { 128 public: 129 virtual pp::Instance* CreateInstance(PP_Instance instance) { 130 return new MyInstance(instance); 131 } 132}; 133 134namespace pp { 135 136Module* CreateModule() { 137 return new MyModule(); 138} 139 140} // namespace pp 141