1 // Copyright (c) 2012 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.
9 #include "ppapi/c/ppb_console.h"
10 #include "ppapi/c/ppb_input_event.h"
11 #include "ppapi/cpp/graphics_2d.h"
12 #include "ppapi/cpp/image_data.h"
13 #include "ppapi/cpp/input_event.h"
14 #include "ppapi/cpp/instance.h"
15 #include "ppapi/cpp/logging.h"
16 #include "ppapi/cpp/module.h"
17 #include "ppapi/cpp/mouse_lock.h"
18 #include "ppapi/cpp/private/flash_fullscreen.h"
19 #include "ppapi/cpp/rect.h"
20 #include "ppapi/cpp/var.h"
21 #include "ppapi/utility/completion_callback_factory.h"
23 class MyInstance
: public pp::Instance
, public pp::MouseLock
{
25 explicit MyInstance(PP_Instance instance
)
26 : pp::Instance(instance
),
31 pending_paint_(false),
32 waiting_for_flush_completion_(false),
33 callback_factory_(this),
35 flash_fullscreen_(this) {
37 virtual ~MyInstance() {}
39 virtual bool Init(uint32_t argc
, const char* argn
[], const char* argv
[]) {
40 console_
= reinterpret_cast<const PPB_Console
*>(
41 pp::Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE
));
45 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE
|
46 PP_INPUTEVENT_CLASS_KEYBOARD
);
50 virtual bool HandleInputEvent(const pp::InputEvent
& event
) {
51 switch (event
.GetType()) {
52 case PP_INPUTEVENT_TYPE_MOUSEDOWN
: {
53 pp::MouseInputEvent
mouse_event(event
);
54 if (mouse_event
.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT
&&
56 LockMouse(callback_factory_
.NewCallback(&MyInstance::DidLockMouse
));
60 case PP_INPUTEVENT_TYPE_MOUSEMOVE
: {
61 pp::MouseInputEvent
mouse_event(event
);
62 mouse_movement_
= mouse_event
.GetMovement();
63 static unsigned int i
= 0;
64 Log(PP_LOGLEVEL_LOG
, "[%d] movementX: %d; movementY: %d\n", i
++,
65 mouse_movement_
.x(), mouse_movement_
.y());
69 case PP_INPUTEVENT_TYPE_KEYDOWN
: {
70 pp::KeyboardInputEvent
key_event(event
);
71 if (key_event
.GetKeyCode() == 13) {
72 // Lock the mouse when the Enter key is pressed.
76 LockMouse(callback_factory_
.NewCallback(&MyInstance::DidLockMouse
));
78 } else if (key_event
.GetKeyCode() == 70) {
79 // Enter Flash fullscreen mode when the 'f' key is pressed.
80 if (!flash_fullscreen_
.IsFullscreen())
81 flash_fullscreen_
.SetFullscreen(true);
91 virtual void DidChangeView(const pp::Rect
& position
, const pp::Rect
& clip
) {
92 if (position
.size().width() == width_
&&
93 position
.size().height() == height_
)
94 return; // We don't care about the position, only the size.
96 width_
= position
.size().width();
97 height_
= position
.size().height();
99 device_context_
= pp::Graphics2D(this, pp::Size(width_
, height_
), false);
100 if (!BindGraphics(device_context_
))
106 virtual void MouseLockLost() {
108 mouse_locked_
= false;
116 void DidLockMouse(int32_t result
) {
117 mouse_locked_
= result
== PP_OK
;
118 mouse_movement_
.set_x(0);
119 mouse_movement_
.set_y(0);
123 void DidFlush(int32_t result
) {
124 waiting_for_flush_completion_
= false;
125 if (pending_paint_
) {
126 pending_paint_
= false;
132 if (waiting_for_flush_completion_
) {
133 pending_paint_
= true;
137 pp::ImageData image
= PaintImage(width_
, height_
);
138 if (!image
.is_null()) {
139 device_context_
.ReplaceContents(&image
);
140 waiting_for_flush_completion_
= true;
141 device_context_
.Flush(
142 callback_factory_
.NewCallback(&MyInstance::DidFlush
));
146 pp::ImageData
PaintImage(int width
, int height
) {
147 pp::ImageData
image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL
,
148 pp::Size(width
, height
), false);
152 const static int kCenteralSpotRadius
= 5;
153 const static uint32_t kBackgroundColor
= 0xfff0f0f0;
154 const static uint32_t kLockedForegroundColor
= 0xfff08080;
155 const static uint32_t kUnlockedForegroundColor
= 0xff80f080;
157 int center_x
= width
/ 2;
158 int center_y
= height
/ 2;
159 pp::Point
vertex(mouse_movement_
.x() + center_x
,
160 mouse_movement_
.y() + center_y
);
169 bool draw_needle
= GetDistance(mouse_movement_
.x(), mouse_movement_
.y(),
170 0, 0) > kCenteralSpotRadius
;
172 if (abs(mouse_movement_
.x()) >= abs(mouse_movement_
.y())) {
173 anchor_1
.set_x(center_x
);
174 anchor_1
.set_y(center_y
- kCenteralSpotRadius
);
175 anchor_2
.set_x(center_x
);
176 anchor_2
.set_y(center_y
+ kCenteralSpotRadius
);
177 direction
= (mouse_movement_
.x() < 0) ? LEFT
: RIGHT
;
178 if (direction
== LEFT
)
179 anchor_1
.swap(anchor_2
);
181 anchor_1
.set_x(center_x
+ kCenteralSpotRadius
);
182 anchor_1
.set_y(center_y
);
183 anchor_2
.set_x(center_x
- kCenteralSpotRadius
);
184 anchor_2
.set_y(center_y
);
185 direction
= (mouse_movement_
.y() < 0) ? UP
: DOWN
;
187 anchor_1
.swap(anchor_2
);
190 uint32_t foreground_color
= mouse_locked_
? kLockedForegroundColor
:
191 kUnlockedForegroundColor
;
192 for (int y
= 0; y
< image
.size().height(); ++y
) {
193 for (int x
= 0; x
< image
.size().width(); ++x
) {
194 if (GetDistance(x
, y
, center_x
, center_y
) < kCenteralSpotRadius
) {
195 *image
.GetAddr32(pp::Point(x
, y
)) = foreground_color
;
199 bool within_bound_1
=
200 ((y
- anchor_1
.y()) * (vertex
.x() - anchor_1
.x())) >
201 ((vertex
.y() - anchor_1
.y()) * (x
- anchor_1
.x()));
202 bool within_bound_2
=
203 ((y
- anchor_2
.y()) * (vertex
.x() - anchor_2
.x())) <
204 ((vertex
.y() - anchor_2
.y()) * (x
- anchor_2
.x()));
205 bool within_bound_3
=
206 (direction
== UP
&& y
< center_y
) ||
207 (direction
== DOWN
&& y
> center_y
) ||
208 (direction
== LEFT
&& x
< center_x
) ||
209 (direction
== RIGHT
&& x
> center_x
);
211 if (within_bound_1
&& within_bound_2
&& within_bound_3
) {
212 *image
.GetAddr32(pp::Point(x
, y
)) = foreground_color
;
216 *image
.GetAddr32(pp::Point(x
, y
)) = kBackgroundColor
;
223 double GetDistance(int point_1_x
, int point_1_y
,
224 int point_2_x
, int point_2_y
) {
225 return sqrt(pow(static_cast<double>(point_1_x
- point_2_x
), 2) +
226 pow(static_cast<double>(point_1_y
- point_2_y
), 2));
229 void Log(PP_LogLevel level
, const char* format
, ...) {
231 va_start(args
, format
);
233 vsnprintf(buf
, sizeof(buf
) - 1, format
, args
);
234 buf
[sizeof(buf
) - 1] = '\0';
238 console_
->Log(pp_instance(), level
, value
.pp_var());
245 pp::Point mouse_movement_
;
248 bool waiting_for_flush_completion_
;
250 pp::CompletionCallbackFactory
<MyInstance
> callback_factory_
;
252 const PPB_Console
* console_
;
254 pp::FlashFullscreen flash_fullscreen_
;
256 pp::Graphics2D device_context_
;
259 // This object is the global object representing this plugin library as long
261 class MyModule
: public pp::Module
{
263 MyModule() : pp::Module() {}
264 virtual ~MyModule() {}
266 // Override CreateInstance to create your customized Instance object.
267 virtual pp::Instance
* CreateInstance(PP_Instance instance
) {
268 return new MyInstance(instance
);
274 // Factory function for your specialization of the Module object.
275 Module
* CreateModule() {
276 return new MyModule();