Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(214)

Side by Side Diff: ppapi/examples/mouse_lock/mouse_lock.cc

Issue 7863003: Mouse lock implementation, including the renderer side and the Windows version of the browser side. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove two tab chars. Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 <cmath>
6 #include <stdarg.h>
7 #include <stdio.h>
8
9 #include "ppapi/c/dev/ppb_console_dev.h"
10 #include "ppapi/c/ppb_input_event.h"
11 #include "ppapi/cpp/completion_callback.h"
12 #include "ppapi/cpp/dev/mouse_lock_dev.h"
13 #include "ppapi/cpp/graphics_2d.h"
14 #include "ppapi/cpp/image_data.h"
15 #include "ppapi/cpp/input_event.h"
16 #include "ppapi/cpp/instance.h"
17 #include "ppapi/cpp/logging.h"
18 #include "ppapi/cpp/module.h"
19 #include "ppapi/cpp/rect.h"
20 #include "ppapi/cpp/var.h"
21
22 class MyInstance : public pp::Instance, public pp::MouseLock_Dev {
23 public:
24 explicit MyInstance(PP_Instance instance)
25 : pp::Instance(instance),
26 pp::MouseLock_Dev(this),
27 width_(0),
28 height_(0),
29 mouse_locked_(false),
30 pending_paint_(false),
31 waiting_for_flush_completion_(false),
32 callback_factory_(this),
33 console_(NULL) {
34 }
35 virtual ~MyInstance() {}
36
37 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
38 console_ = reinterpret_cast<const PPB_Console_Dev*>(
39 pp::Module::Get()->GetBrowserInterface(PPB_CONSOLE_DEV_INTERFACE));
40 if (!console_)
41 return false;
42
43 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
44 PP_INPUTEVENT_CLASS_KEYBOARD);
45 return true;
46 }
47
48 virtual bool HandleInputEvent(const pp::InputEvent& event) {
49 switch (event.GetType()) {
50 case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
51 pp::MouseInputEvent mouse_event(event);
52 if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT &&
53 !mouse_locked_) {
54 LockMouse(
55 callback_factory_.NewRequiredCallback(&MyInstance::DidLockMouse));
56 } else if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_RIGHT &&
57 mouse_locked_) {
58 UnlockMouse();
59 }
60 return true;
61 }
62 case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
63 pp::MouseInputEvent mouse_event(event);
64 pp::Point movement = mouse_event.GetMovement();
65 static unsigned int i = 0;
66 Log(PP_LOGLEVEL_LOG, "[%d] movementX: %d; movementY: %d\n", i++,
67 movement.x(), movement.y());
68
69 if (mouse_locked_) {
scheib 2011/09/14 18:13:23 I still think it's worth verifying that the moveme
yzshen1 2011/09/19 20:48:41 Done. I make the testing plugin also show mouse mo
70 mouse_movement_ = movement;
71 Paint();
72 }
73 return true;
74 }
75 case PP_INPUTEVENT_TYPE_KEYDOWN: {
76 pp::KeyboardInputEvent key_event(event);
77 // Lock the mouse when the Enter key is pressed.
78 if (!mouse_locked_ && key_event.GetKeyCode() == 13) {
79 LockMouse(
80 callback_factory_.NewRequiredCallback(&MyInstance::DidLockMouse));
81 }
82 return true;
83 }
84 default:
85 return false;
86 }
87 }
88
89 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
90 if (position.size().width() == width_ &&
91 position.size().height() == height_)
92 return; // We don't care about the position, only the size.
93
94 width_ = position.size().width();
95 height_ = position.size().height();
96
97 device_context_ = pp::Graphics2D(this, pp::Size(width_, height_), false);
98 if (!BindGraphics(device_context_))
99 return;
100
101 Paint();
102 }
103
104 virtual void MouseLockLost() {
105 if (mouse_locked_) {
106 mouse_locked_ = false;
107 Paint();
108 } else {
109 PP_NOTREACHED();
110 }
111 }
112
113 private:
114 void DidLockMouse(int32_t result) {
115 mouse_locked_ = result == PP_OK;
116 mouse_movement_.set_x(0);
117 mouse_movement_.set_y(0);
118 Paint();
119 }
120
121 void DidFlush(int32_t result) {
122 waiting_for_flush_completion_ = false;
123 if (pending_paint_) {
124 pending_paint_ = false;
125 Paint();
126 }
127 }
128
129 void Paint() {
130 if (waiting_for_flush_completion_) {
131 pending_paint_ = true;
132 return;
133 }
134
135 pp::ImageData image = PaintImage(width_, height_);
136 if (!image.is_null()) {
137 device_context_.ReplaceContents(&image);
138 waiting_for_flush_completion_ = true;
139 device_context_.Flush(
140 callback_factory_.NewRequiredCallback(&MyInstance::DidFlush));
141 }
142 }
143
144 pp::ImageData PaintImage(int width, int height) {
145 pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
146 pp::Size(width, height), false);
147 if (image.is_null())
148 return image;
149
150 const static int kCenteralSpotRadius = 5;
151 const static uint32_t kBackgroundColor = 0xfff0f0f0;
152 const static uint32_t kForegroundColor = 0xfff08080;
153
154 int center_x = width / 2;
155 int center_y = height / 2;
156 pp::Point vertex(mouse_movement_.x() + center_x,
157 mouse_movement_.y() + center_y);
158 pp::Point anchor_1;
159 pp::Point anchor_2;
160 enum {
161 LEFT = 0,
162 RIGHT = 1,
163 UP = 2,
164 DOWN = 3
165 } direction;
166 bool draw_needle = mouse_locked_ &&
167 GetDistance(mouse_movement_.x(), mouse_movement_.y(),
168 0, 0) > kCenteralSpotRadius;
169 if (draw_needle) {
170 if (abs(mouse_movement_.x()) >= abs(mouse_movement_.y())) {
171 anchor_1.set_x(center_x);
172 anchor_1.set_y(center_y - kCenteralSpotRadius);
173 anchor_2.set_x(center_x);
174 anchor_2.set_y(center_y + kCenteralSpotRadius);
175 direction = (mouse_movement_.x() < 0) ? LEFT : RIGHT;
176 if (direction == LEFT)
177 anchor_1.swap(anchor_2);
178 } else {
179 anchor_1.set_x(center_x + kCenteralSpotRadius);
180 anchor_1.set_y(center_y);
181 anchor_2.set_x(center_x - kCenteralSpotRadius);
182 anchor_2.set_y(center_y);
183 direction = (mouse_movement_.y() < 0) ? UP : DOWN;
184 if (direction == UP)
185 anchor_1.swap(anchor_2);
186 }
187 }
188
189 for (int y = 0; y < image.size().height(); ++y) {
190 for (int x = 0; x < image.size().width(); ++x) {
191 if (mouse_locked_) {
192 if (GetDistance(x, y, center_x, center_y) < kCenteralSpotRadius) {
193 *image.GetAddr32(pp::Point(x, y)) = kForegroundColor;
194 continue;
195 }
196 if (draw_needle) {
197 bool within_bound_1 =
198 ((y - anchor_1.y()) * (vertex.x() - anchor_1.x())) >
199 ((vertex.y() - anchor_1.y()) * (x - anchor_1.x()));
200 bool within_bound_2 =
201 ((y - anchor_2.y()) * (vertex.x() - anchor_2.x())) <
202 ((vertex.y() - anchor_2.y()) * (x - anchor_2.x()));
203 bool within_bound_3 =
204 (direction == UP && y < center_y) ||
205 (direction == DOWN && y > center_y) ||
206 (direction == LEFT && x < center_x) ||
207 (direction == RIGHT && x > center_y);
208
209 if (within_bound_1 && within_bound_2 && within_bound_3) {
210 *image.GetAddr32(pp::Point(x, y)) = kForegroundColor;
211 continue;
212 }
213 }
214 }
215 *image.GetAddr32(pp::Point(x, y)) = kBackgroundColor;
216 }
217 }
218
219 return image;
220 }
221
222 double GetDistance(int point_1_x, int point_1_y,
223 int point_2_x, int point_2_y) {
224 return sqrt(pow(static_cast<double>(point_1_x - point_2_x), 2) +
225 pow(static_cast<double>(point_1_y - point_2_y), 2));
226 }
227
228 void Log(PP_LogLevel_Dev level, const char* format, ...) {
229 va_list args;
230 va_start(args, format);
231 char buf[512];
232 vsnprintf(buf, sizeof(buf) - 1, format, args);
233 buf[sizeof(buf) - 1] = '\0';
234 va_end(args);
235
236 pp::Var value(buf);
237 console_->Log(pp_instance(), level, value.pp_var());
238 }
239
240 int width_;
241 int height_;
242
243 bool mouse_locked_;
244 // Only valid when the mouse is locked.
245 pp::Point mouse_movement_;
246
247 bool pending_paint_;
248 bool waiting_for_flush_completion_;
249
250 pp::CompletionCallbackFactory<MyInstance> callback_factory_;
251
252 const PPB_Console_Dev* console_;
253
254 pp::Graphics2D device_context_;
255 };
256
257 // This object is the global object representing this plugin library as long
258 // as it is loaded.
259 class MyModule : public pp::Module {
260 public:
261 MyModule() : pp::Module() {}
262 virtual ~MyModule() {}
263
264 // Override CreateInstance to create your customized Instance object.
265 virtual pp::Instance* CreateInstance(PP_Instance instance) {
266 return new MyInstance(instance);
267 }
268 };
269
270 namespace pp {
271
272 // Factory function for your specialization of the Module object.
273 Module* CreateModule() {
274 return new MyModule();
275 }
276
277 } // namespace pp
278
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698