| Index: ppapi/examples/mouse_lock/mouse_lock.cc
|
| diff --git a/ppapi/examples/mouse_lock/mouse_lock.cc b/ppapi/examples/mouse_lock/mouse_lock.cc
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..95806cf5046505b63a18924eefd49957c9966c42
|
| --- /dev/null
|
| +++ b/ppapi/examples/mouse_lock/mouse_lock.cc
|
| @@ -0,0 +1,272 @@
|
| +// Copyright (c) 2011 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.
|
| +
|
| +#include <cmath>
|
| +#include <stdarg.h>
|
| +#include <stdio.h>
|
| +
|
| +#include "ppapi/c/dev/ppb_console_dev.h"
|
| +#include "ppapi/c/ppb_input_event.h"
|
| +#include "ppapi/cpp/completion_callback.h"
|
| +#include "ppapi/cpp/dev/mouse_lock_dev.h"
|
| +#include "ppapi/cpp/graphics_2d.h"
|
| +#include "ppapi/cpp/image_data.h"
|
| +#include "ppapi/cpp/input_event.h"
|
| +#include "ppapi/cpp/instance.h"
|
| +#include "ppapi/cpp/logging.h"
|
| +#include "ppapi/cpp/module.h"
|
| +#include "ppapi/cpp/rect.h"
|
| +#include "ppapi/cpp/var.h"
|
| +
|
| +class MyInstance : public pp::Instance, public pp::MouseLock_Dev {
|
| + public:
|
| + explicit MyInstance(PP_Instance instance)
|
| + : pp::Instance(instance),
|
| + pp::MouseLock_Dev(this),
|
| + width_(0),
|
| + height_(0),
|
| + mouse_locked_(false),
|
| + pending_paint_(false),
|
| + waiting_for_flush_completion_(false),
|
| + callback_factory_(this),
|
| + console_(NULL) {
|
| + }
|
| + virtual ~MyInstance() {}
|
| +
|
| + virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
|
| + console_ = reinterpret_cast<const PPB_Console_Dev*>(
|
| + pp::Module::Get()->GetBrowserInterface(PPB_CONSOLE_DEV_INTERFACE));
|
| + if (!console_)
|
| + return false;
|
| +
|
| + RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
|
| + PP_INPUTEVENT_CLASS_KEYBOARD);
|
| + return true;
|
| + }
|
| +
|
| + virtual bool HandleInputEvent(const pp::InputEvent& event) {
|
| + switch (event.GetType()) {
|
| + case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
|
| + pp::MouseInputEvent mouse_event(event);
|
| + if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT &&
|
| + !mouse_locked_) {
|
| + LockMouse(
|
| + callback_factory_.NewRequiredCallback(&MyInstance::DidLockMouse));
|
| + } else if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_RIGHT &&
|
| + mouse_locked_) {
|
| + UnlockMouse();
|
| + }
|
| + return true;
|
| + }
|
| + case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
|
| + pp::MouseInputEvent mouse_event(event);
|
| + mouse_movement_ = mouse_event.GetMovement();
|
| + static unsigned int i = 0;
|
| + Log(PP_LOGLEVEL_LOG, "[%d] movementX: %d; movementY: %d\n", i++,
|
| + mouse_movement_.x(), mouse_movement_.y());
|
| + Paint();
|
| + return true;
|
| + }
|
| + case PP_INPUTEVENT_TYPE_KEYDOWN: {
|
| + pp::KeyboardInputEvent key_event(event);
|
| + // Lock the mouse when the Enter key is pressed.
|
| + if (!mouse_locked_ && key_event.GetKeyCode() == 13) {
|
| + LockMouse(
|
| + callback_factory_.NewRequiredCallback(&MyInstance::DidLockMouse));
|
| + }
|
| + return true;
|
| + }
|
| + default:
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
|
| + if (position.size().width() == width_ &&
|
| + position.size().height() == height_)
|
| + return; // We don't care about the position, only the size.
|
| +
|
| + width_ = position.size().width();
|
| + height_ = position.size().height();
|
| +
|
| + device_context_ = pp::Graphics2D(this, pp::Size(width_, height_), false);
|
| + if (!BindGraphics(device_context_))
|
| + return;
|
| +
|
| + Paint();
|
| + }
|
| +
|
| + virtual void MouseLockLost() {
|
| + if (mouse_locked_) {
|
| + mouse_locked_ = false;
|
| + Paint();
|
| + } else {
|
| + PP_NOTREACHED();
|
| + }
|
| + }
|
| +
|
| + private:
|
| + void DidLockMouse(int32_t result) {
|
| + mouse_locked_ = result == PP_OK;
|
| + mouse_movement_.set_x(0);
|
| + mouse_movement_.set_y(0);
|
| + Paint();
|
| + }
|
| +
|
| + void DidFlush(int32_t result) {
|
| + waiting_for_flush_completion_ = false;
|
| + if (pending_paint_) {
|
| + pending_paint_ = false;
|
| + Paint();
|
| + }
|
| + }
|
| +
|
| + void Paint() {
|
| + if (waiting_for_flush_completion_) {
|
| + pending_paint_ = true;
|
| + return;
|
| + }
|
| +
|
| + pp::ImageData image = PaintImage(width_, height_);
|
| + if (!image.is_null()) {
|
| + device_context_.ReplaceContents(&image);
|
| + waiting_for_flush_completion_ = true;
|
| + device_context_.Flush(
|
| + callback_factory_.NewRequiredCallback(&MyInstance::DidFlush));
|
| + }
|
| + }
|
| +
|
| + pp::ImageData PaintImage(int width, int height) {
|
| + pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
|
| + pp::Size(width, height), false);
|
| + if (image.is_null())
|
| + return image;
|
| +
|
| + const static int kCenteralSpotRadius = 5;
|
| + const static uint32_t kBackgroundColor = 0xfff0f0f0;
|
| + const static uint32_t kLockedForegroundColor = 0xfff08080;
|
| + const static uint32_t kUnlockedForegroundColor = 0xff80f080;
|
| +
|
| + int center_x = width / 2;
|
| + int center_y = height / 2;
|
| + pp::Point vertex(mouse_movement_.x() + center_x,
|
| + mouse_movement_.y() + center_y);
|
| + pp::Point anchor_1;
|
| + pp::Point anchor_2;
|
| + enum {
|
| + LEFT = 0,
|
| + RIGHT = 1,
|
| + UP = 2,
|
| + DOWN = 3
|
| + } direction;
|
| + bool draw_needle = GetDistance(mouse_movement_.x(), mouse_movement_.y(),
|
| + 0, 0) > kCenteralSpotRadius;
|
| + if (draw_needle) {
|
| + if (abs(mouse_movement_.x()) >= abs(mouse_movement_.y())) {
|
| + anchor_1.set_x(center_x);
|
| + anchor_1.set_y(center_y - kCenteralSpotRadius);
|
| + anchor_2.set_x(center_x);
|
| + anchor_2.set_y(center_y + kCenteralSpotRadius);
|
| + direction = (mouse_movement_.x() < 0) ? LEFT : RIGHT;
|
| + if (direction == LEFT)
|
| + anchor_1.swap(anchor_2);
|
| + } else {
|
| + anchor_1.set_x(center_x + kCenteralSpotRadius);
|
| + anchor_1.set_y(center_y);
|
| + anchor_2.set_x(center_x - kCenteralSpotRadius);
|
| + anchor_2.set_y(center_y);
|
| + direction = (mouse_movement_.y() < 0) ? UP : DOWN;
|
| + if (direction == UP)
|
| + anchor_1.swap(anchor_2);
|
| + }
|
| + }
|
| + uint32_t foreground_color = mouse_locked_ ? kLockedForegroundColor :
|
| + kUnlockedForegroundColor;
|
| + for (int y = 0; y < image.size().height(); ++y) {
|
| + for (int x = 0; x < image.size().width(); ++x) {
|
| + if (GetDistance(x, y, center_x, center_y) < kCenteralSpotRadius) {
|
| + *image.GetAddr32(pp::Point(x, y)) = foreground_color;
|
| + continue;
|
| + }
|
| + if (draw_needle) {
|
| + bool within_bound_1 =
|
| + ((y - anchor_1.y()) * (vertex.x() - anchor_1.x())) >
|
| + ((vertex.y() - anchor_1.y()) * (x - anchor_1.x()));
|
| + bool within_bound_2 =
|
| + ((y - anchor_2.y()) * (vertex.x() - anchor_2.x())) <
|
| + ((vertex.y() - anchor_2.y()) * (x - anchor_2.x()));
|
| + bool within_bound_3 =
|
| + (direction == UP && y < center_y) ||
|
| + (direction == DOWN && y > center_y) ||
|
| + (direction == LEFT && x < center_x) ||
|
| + (direction == RIGHT && x > center_y);
|
| +
|
| + if (within_bound_1 && within_bound_2 && within_bound_3) {
|
| + *image.GetAddr32(pp::Point(x, y)) = foreground_color;
|
| + continue;
|
| + }
|
| + }
|
| + *image.GetAddr32(pp::Point(x, y)) = kBackgroundColor;
|
| + }
|
| + }
|
| +
|
| + return image;
|
| + }
|
| +
|
| + double GetDistance(int point_1_x, int point_1_y,
|
| + int point_2_x, int point_2_y) {
|
| + return sqrt(pow(static_cast<double>(point_1_x - point_2_x), 2) +
|
| + pow(static_cast<double>(point_1_y - point_2_y), 2));
|
| + }
|
| +
|
| + void Log(PP_LogLevel_Dev level, const char* format, ...) {
|
| + va_list args;
|
| + va_start(args, format);
|
| + char buf[512];
|
| + vsnprintf(buf, sizeof(buf) - 1, format, args);
|
| + buf[sizeof(buf) - 1] = '\0';
|
| + va_end(args);
|
| +
|
| + pp::Var value(buf);
|
| + console_->Log(pp_instance(), level, value.pp_var());
|
| + }
|
| +
|
| + int width_;
|
| + int height_;
|
| +
|
| + bool mouse_locked_;
|
| + pp::Point mouse_movement_;
|
| +
|
| + bool pending_paint_;
|
| + bool waiting_for_flush_completion_;
|
| +
|
| + pp::CompletionCallbackFactory<MyInstance> callback_factory_;
|
| +
|
| + const PPB_Console_Dev* console_;
|
| +
|
| + pp::Graphics2D device_context_;
|
| +};
|
| +
|
| +// This object is the global object representing this plugin library as long
|
| +// as it is loaded.
|
| +class MyModule : public pp::Module {
|
| + public:
|
| + MyModule() : pp::Module() {}
|
| + virtual ~MyModule() {}
|
| +
|
| + // Override CreateInstance to create your customized Instance object.
|
| + virtual pp::Instance* CreateInstance(PP_Instance instance) {
|
| + return new MyInstance(instance);
|
| + }
|
| +};
|
| +
|
| +namespace pp {
|
| +
|
| +// Factory function for your specialization of the Module object.
|
| +Module* CreateModule() {
|
| + return new MyModule();
|
| +}
|
| +
|
| +} // namespace pp
|
| +
|
|
|