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

Side by Side Diff: native_client_sdk/src/examples/api/mouse_lock/mouselock.cc

Issue 14607005: [NaCl SDK] Cleanup examples. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: feedback Created 7 years, 7 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) 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.
4
5 #include <cmath>
6 #include <cstdlib>
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <string.h>
10
11 #include <algorithm>
12
13 #include "mouselock.h"
14
15 #ifdef WIN32
16 #undef min
17 #undef max
18 #undef PostMessage
19 #endif
20
21 // Indicate the direction of the mouse location relative to the center of the
22 // view. These values are used to determine which 2D quadrant the needle lies
23 // in.
24 typedef enum {
25 kLeft = 0,
26 kRight = 1,
27 kUp = 2,
28 kDown = 3
29 } MouseDirection;
30
31 namespace {
32 const int kCentralSpotRadius = 5;
33 const uint32_t kReturnKeyCode = 13;
34 const uint32_t kBackgroundColor = 0xff606060;
35 const uint32_t kForegroundColor = 0xfff08080;
36 } // namespace
37
38 namespace mouselock {
39
40 MouseLockInstance::~MouseLockInstance() {
41 free(background_scanline_);
42 background_scanline_ = NULL;
43 }
44
45 bool MouseLockInstance::Init(uint32_t argc,
46 const char* argn[],
47 const char* argv[]) {
48 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_KEYBOARD);
49 return true;
50 }
51
52 bool MouseLockInstance::HandleInputEvent(const pp::InputEvent& event) {
53 switch (event.GetType()) {
54 case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
55 if (mouse_locked_) {
56 UnlockMouse();
57 } else {
58 LockMouse(
59 callback_factory_.NewCallback(&MouseLockInstance::DidLockMouse));
60 }
61 return true;
62 }
63
64 case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
65 pp::MouseInputEvent mouse_event(event);
66 mouse_movement_ = mouse_event.GetMovement();
67 Paint();
68 return true;
69 }
70
71 case PP_INPUTEVENT_TYPE_KEYDOWN: {
72 pp::KeyboardInputEvent key_event(event);
73
74 // Switch in and out of fullscreen when 'Enter' is hit
75 if (key_event.GetKeyCode() == kReturnKeyCode) {
76 // Ignore switch if in transition
77 if (!is_context_bound_)
78 return true;
79
80 if (fullscreen_.IsFullscreen()) {
81 if (!fullscreen_.SetFullscreen(false)) {
82 Log("Could not leave fullscreen mode\n");
83 } else {
84 is_context_bound_ = false;
85 }
86 } else {
87 if (!fullscreen_.SetFullscreen(true)) {
88 Log("Could not enter fullscreen mode\n");
89 } else {
90 is_context_bound_ = false;
91 }
92 }
93 }
94 return true;
95 }
96
97 case PP_INPUTEVENT_TYPE_MOUSEUP:
98 case PP_INPUTEVENT_TYPE_MOUSEENTER:
99 case PP_INPUTEVENT_TYPE_MOUSELEAVE:
100 case PP_INPUTEVENT_TYPE_WHEEL:
101 case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
102 case PP_INPUTEVENT_TYPE_KEYUP:
103 case PP_INPUTEVENT_TYPE_CHAR:
104 case PP_INPUTEVENT_TYPE_CONTEXTMENU:
105 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
106 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
107 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
108 case PP_INPUTEVENT_TYPE_IME_TEXT:
109 case PP_INPUTEVENT_TYPE_UNDEFINED:
110 case PP_INPUTEVENT_TYPE_TOUCHSTART:
111 case PP_INPUTEVENT_TYPE_TOUCHMOVE:
112 case PP_INPUTEVENT_TYPE_TOUCHEND:
113 case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
114 default:
115 return false;
116 }
117 }
118
119 void MouseLockInstance::DidChangeView(const pp::View& view) {
120 // DidChangeView can get called for many reasons, so we only want to
121 // rebuild the device context if we really need to.
122
123 if ((size_ == view.GetRect().size()) &&
124 (was_fullscreen_ == view.IsFullscreen()) && is_context_bound_) {
125 Log("DidChangeView SKIP %d,%d FULL=%s CTX Bound=%s",
126 view.GetRect().width(),
127 view.GetRect().height(),
128 view.IsFullscreen() ? "true" : "false",
129 is_context_bound_ ? "true" : "false");
130 return;
131 }
132
133 Log("DidChangeView DO %d,%d FULL=%s CTX Bound=%s",
134 view.GetRect().width(),
135 view.GetRect().height(),
136 view.IsFullscreen() ? "true" : "false",
137 is_context_bound_ ? "true" : "false");
138
139 size_ = view.GetRect().size();
140 device_context_ = pp::Graphics2D(this, size_, false);
141 waiting_for_flush_completion_ = false;
142
143 is_context_bound_ = BindGraphics(device_context_);
144 if (!is_context_bound_) {
145 Log("Could not bind to 2D context\n.");
146 return;
147 } else {
148 Log("Bound to 2D context size %d,%d.\n", size_.width(), size_.height());
149 }
150
151 // Create a scanline for fill.
152 delete[] background_scanline_;
153 background_scanline_ = new uint32_t[size_.width()];
154 uint32_t* bg_pixel = background_scanline_;
155 for (int x = 0; x < size_.width(); ++x) {
156 *bg_pixel++ = kBackgroundColor;
157 }
158
159 // Remember if we are fullscreen or not
160 was_fullscreen_ = view.IsFullscreen();
161
162 // Paint this context
163 Paint();
164 }
165
166 void MouseLockInstance::MouseLockLost() {
167 if (mouse_locked_) {
168 Log("Mouselock unlocked.\n");
169 mouse_locked_ = false;
170 Paint();
171 }
172 }
173
174 void MouseLockInstance::DidLockMouse(int32_t result) {
175 mouse_locked_ = result == PP_OK;
176 if (result != PP_OK) {
177 Log("Mouselock failed with failed with error number %d.\n", result);
178 }
179 mouse_movement_.set_x(0);
180 mouse_movement_.set_y(0);
181 Paint();
182 }
183
184 void MouseLockInstance::DidFlush(int32_t result) {
185 if (result != 0)
186 Log("Flushed failed with error number %d.\n", result);
187 waiting_for_flush_completion_ = false;
188 }
189
190 void MouseLockInstance::Paint() {
191 // If we are already waiting to paint...
192 if (waiting_for_flush_completion_) {
193 return;
194 }
195
196 pp::ImageData image = PaintImage(size_);
197 if (image.is_null()) {
198 Log("Could not create image data\n");
199 return;
200 }
201
202 device_context_.ReplaceContents(&image);
203 waiting_for_flush_completion_ = true;
204 device_context_.Flush(
205 callback_factory_.NewCallback(&MouseLockInstance::DidFlush));
206 }
207
208 pp::ImageData MouseLockInstance::PaintImage(const pp::Size& size) {
209 pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
210 if (image.is_null() || image.data() == NULL) {
211 Log("Skipping image.\n");
212 return image;
213 }
214
215 ClearToBackground(&image);
216
217 DrawCenterSpot(&image, kForegroundColor);
218 DrawNeedle(&image, kForegroundColor);
219 return image;
220 }
221
222 void MouseLockInstance::ClearToBackground(pp::ImageData* image) {
223 if (image == NULL) {
224 Log("ClearToBackground with NULL image.");
225 return;
226 }
227 if (background_scanline_ == NULL) {
228 Log("ClearToBackground with no scanline.");
229 return;
230 }
231 int image_height = image->size().height();
232 int image_width = image->size().width();
233
234 for (int y = 0; y < image_height; ++y) {
235 uint32_t* scanline = image->GetAddr32(pp::Point(0, y));
236 memcpy(scanline,
237 background_scanline_,
238 image_width * sizeof(*background_scanline_));
239 }
240 }
241
242 void MouseLockInstance::DrawCenterSpot(pp::ImageData* image,
243 uint32_t spot_color) {
244 if (image == NULL) {
245 Log("DrawCenterSpot with NULL image");
246 return;
247 }
248 // Draw the center spot. The ROI is bounded by the size of the spot, plus
249 // one pixel.
250 int center_x = image->size().width() / 2;
251 int center_y = image->size().height() / 2;
252 int region_of_interest_radius = kCentralSpotRadius + 1;
253
254 pp::Point left_top(std::max(0, center_x - region_of_interest_radius),
255 std::max(0, center_y - region_of_interest_radius));
256 pp::Point right_bottom(
257 std::min(image->size().width(), center_x + region_of_interest_radius),
258 std::min(image->size().height(), center_y + region_of_interest_radius));
259 for (int y = left_top.y(); y < right_bottom.y(); ++y) {
260 for (int x = left_top.x(); x < right_bottom.x(); ++x) {
261 if (GetDistance(x, y, center_x, center_y) < kCentralSpotRadius) {
262 *image->GetAddr32(pp::Point(x, y)) = spot_color;
263 }
264 }
265 }
266 }
267
268 void MouseLockInstance::DrawNeedle(pp::ImageData* image,
269 uint32_t needle_color) {
270 if (image == NULL) {
271 Log("DrawNeedle with NULL image");
272 return;
273 }
274 if (GetDistance(mouse_movement_.x(), mouse_movement_.y(), 0, 0) <=
275 kCentralSpotRadius) {
276 return;
277 }
278
279 int abs_mouse_x = std::abs(mouse_movement_.x());
280 int abs_mouse_y = std::abs(mouse_movement_.y());
281 int center_x = image->size().width() / 2;
282 int center_y = image->size().height() / 2;
283 pp::Point vertex(mouse_movement_.x() + center_x,
284 mouse_movement_.y() + center_y);
285 pp::Point anchor_1;
286 pp::Point anchor_2;
287 MouseDirection direction = kLeft;
288
289 if (abs_mouse_x >= abs_mouse_y) {
290 anchor_1.set_x(center_x);
291 anchor_1.set_y(center_y - kCentralSpotRadius);
292 anchor_2.set_x(center_x);
293 anchor_2.set_y(center_y + kCentralSpotRadius);
294 direction = (mouse_movement_.x() < 0) ? kLeft : kRight;
295 if (direction == kLeft)
296 anchor_1.swap(anchor_2);
297 } else {
298 anchor_1.set_x(center_x + kCentralSpotRadius);
299 anchor_1.set_y(center_y);
300 anchor_2.set_x(center_x - kCentralSpotRadius);
301 anchor_2.set_y(center_y);
302 direction = (mouse_movement_.y() < 0) ? kUp : kDown;
303 if (direction == kUp)
304 anchor_1.swap(anchor_2);
305 }
306
307 pp::Point left_top(std::max(0, center_x - abs_mouse_x),
308 std::max(0, center_y - abs_mouse_y));
309 pp::Point right_bottom(
310 std::min(image->size().width(), center_x + abs_mouse_x),
311 std::min(image->size().height(), center_y + abs_mouse_y));
312 for (int y = left_top.y(); y < right_bottom.y(); ++y) {
313 for (int x = left_top.x(); x < right_bottom.x(); ++x) {
314 bool within_bound_1 = ((y - anchor_1.y()) * (vertex.x() - anchor_1.x())) >
315 ((vertex.y() - anchor_1.y()) * (x - anchor_1.x()));
316 bool within_bound_2 = ((y - anchor_2.y()) * (vertex.x() - anchor_2.x())) <
317 ((vertex.y() - anchor_2.y()) * (x - anchor_2.x()));
318 bool within_bound_3 = (direction == kUp && y < center_y) ||
319 (direction == kDown && y > center_y) ||
320 (direction == kLeft && x < center_x) ||
321 (direction == kRight && x > center_x);
322
323 if (within_bound_1 && within_bound_2 && within_bound_3) {
324 *image->GetAddr32(pp::Point(x, y)) = needle_color;
325 }
326 }
327 }
328 }
329
330 void MouseLockInstance::Log(const char* format, ...) {
331 static PPB_Console* console =
332 (PPB_Console*)pp::Module::Get()->GetBrowserInterface(
333 PPB_CONSOLE_INTERFACE);
334
335 if (NULL == console)
336 return;
337 va_list args;
338 va_start(args, format);
339 char buf[512];
340 vsnprintf(buf, sizeof(buf) - 1, format, args);
341 buf[sizeof(buf) - 1] = '\0';
342 va_end(args);
343
344 pp::Var value(buf);
345 console->Log(pp_instance(), PP_LOGLEVEL_ERROR, value.pp_var());
346 }
347
348 } // namespace mouselock
349
350 // This object is the global object representing this plugin library as long
351 // as it is loaded.
352 class MouseLockModule : public pp::Module {
353 public:
354 MouseLockModule() : pp::Module() {}
355 virtual ~MouseLockModule() {}
356
357 // Override CreateInstance to create your customized Instance object.
358 virtual pp::Instance* CreateInstance(PP_Instance instance) {
359 return new mouselock::MouseLockInstance(instance);
360 }
361 };
362
363 namespace pp {
364
365 // Factory function for your specialization of the Module object.
366 Module* CreateModule() { return new MouseLockModule(); }
367
368 } // namespace pp
OLDNEW
« no previous file with comments | « native_client_sdk/src/examples/api/mouse_lock/mouselock.h ('k') | native_client_sdk/src/examples/api/url_loader/example.dsc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698