|
OLD | NEW |
---|---|
(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 "examples/mouselock/mouselock.h" | |
cstefansen
2011/11/10 17:53:03
Nit: Google style suggests putting this include fi
der Springer
2011/11/11 19:23:01
Done.
| |
10 | |
11 typedef enum { | |
gwink1
2011/11/10 14:54:33
It would be nice to know what these are used for.
der Springer
2011/11/11 19:23:01
Done.
| |
12 kLeft = 0, | |
13 kRight = 1, | |
14 kUp = 2, | |
15 kDown = 3 | |
16 } MouseDirection; | |
17 | |
18 namespace { | |
19 const int kCentralSpotRadius = 5; | |
20 const uint32_t kReturnKeyCode = 13; | |
21 const uint32_t kBackgroundColor = 0xff606060; | |
22 const uint32_t kLockedForegroundColor = 0xfff08080; | |
23 const uint32_t kUnlockedForegroundColor = 0xff80f080; | |
24 } // namespace | |
25 | |
26 namespace mouselock { | |
27 | |
28 bool MouseLockInstance::Init(uint32_t argc, | |
29 const char* argn[], | |
30 const char* argv[]) { | |
31 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | | |
32 PP_INPUTEVENT_CLASS_KEYBOARD); | |
33 return true; | |
34 } | |
35 | |
36 bool MouseLockInstance::HandleInputEvent(const pp::InputEvent& event) { | |
37 switch (event.GetType()) { | |
38 case PP_INPUTEVENT_TYPE_UNDEFINED: | |
cstefansen
2011/11/10 17:53:03
Why not move this one down to the list of all the
der Springer
2011/11/11 19:23:01
Done.
| |
39 break; | |
40 | |
41 case PP_INPUTEVENT_TYPE_MOUSEDOWN: { | |
42 if (fullscreen_.IsFullscreen()) { | |
43 // Leaving fullscreen mode also unlocks the mouse if it was locked. | |
44 // In this case, the browser will call MouseLockLost() on this | |
45 // instance. | |
46 fullscreen_pending_ = false; | |
47 if (!fullscreen_.SetFullscreen(false)) { | |
48 Log("Could not leave fullscreen mode\n"); | |
49 } | |
50 } else { | |
51 if (!fullscreen_.SetFullscreen(true)) { | |
52 Log("Could not set fullscreen mode\n"); | |
53 } else { | |
54 fullscreen_pending_ = true; | |
55 pp::MouseInputEvent mouse_event(event); | |
56 if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT && | |
57 !mouse_locked_) { | |
58 LockMouse(callback_factory_.NewRequiredCallback( | |
59 &MouseLockInstance::DidLockMouse)); | |
60 } | |
61 } | |
62 } | |
63 return true; | |
64 } | |
65 | |
66 case PP_INPUTEVENT_TYPE_MOUSEMOVE: { | |
67 pp::MouseInputEvent mouse_event(event); | |
68 mouse_movement_ = mouse_event.GetMovement(); | |
69 Paint(); | |
70 return true; | |
71 } | |
72 | |
73 case PP_INPUTEVENT_TYPE_KEYDOWN: { | |
74 pp::KeyboardInputEvent key_event(event); | |
75 // Lock the mouse when the Enter key is pressed. | |
76 if (key_event.GetKeyCode() == kReturnKeyCode) { | |
77 if (mouse_locked_) { | |
78 UnlockMouse(); | |
79 } else { | |
80 LockMouse(callback_factory_.NewRequiredCallback( | |
81 &MouseLockInstance::DidLockMouse)); | |
82 } | |
83 } | |
84 return true; | |
85 } | |
86 | |
87 case PP_INPUTEVENT_TYPE_MOUSEUP: | |
88 case PP_INPUTEVENT_TYPE_MOUSEENTER: | |
89 case PP_INPUTEVENT_TYPE_MOUSELEAVE: | |
90 case PP_INPUTEVENT_TYPE_WHEEL: | |
91 case PP_INPUTEVENT_TYPE_RAWKEYDOWN: | |
92 case PP_INPUTEVENT_TYPE_KEYUP: | |
93 case PP_INPUTEVENT_TYPE_CHAR: | |
94 case PP_INPUTEVENT_TYPE_CONTEXTMENU: | |
95 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START: | |
96 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE: | |
97 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END: | |
98 case PP_INPUTEVENT_TYPE_IME_TEXT: | |
99 default: | |
100 break; | |
Matt Ball
2011/11/10 15:03:11
If you're mixing some cases using 'break' and othe
der Springer
2011/11/11 19:23:01
Done.
| |
101 } | |
102 return false; | |
103 } | |
104 | |
105 void MouseLockInstance::DidChangeView(const pp::Rect& position, | |
106 const pp::Rect& clip) { | |
107 if (fullscreen_pending_ && !saw_first_didchangeview_) { | |
gwink1
2011/11/10 14:54:33
One comment I got from Polina, on the fullscreen s
der Springer
2011/11/11 19:23:01
Done.
| |
108 saw_first_didchangeview_ = true; | |
109 // Wait for the 2nd DidChangeView. | |
110 return; | |
111 } else if (fullscreen_pending_) { | |
112 fullscreen_pending_ = false; | |
113 saw_first_didchangeview_ = false; // Reset. | |
114 } | |
115 | |
116 int width = position.size().width(); | |
117 int height = position.size().height(); | |
118 if (width == width_ && height == height_) { | |
119 return; | |
120 } | |
121 width_ = width; | |
122 height_ = height; | |
123 | |
124 device_context_ = pp::Graphics2D(this, pp::Size(width_, height_), false); | |
125 waiting_for_flush_completion_ = false; | |
126 if (!BindGraphics(device_context_)) { | |
cstefansen
2011/11/10 17:53:03
Maybe issue a log message here?
der Springer
2011/11/11 19:23:01
Done.
| |
127 return; | |
128 } | |
129 | |
130 Paint(); | |
131 } | |
132 | |
133 void MouseLockInstance::MouseLockLost() { | |
134 if (mouse_locked_) { | |
135 mouse_locked_ = false; | |
136 Paint(); | |
137 } else { | |
138 PP_NOTREACHED(); | |
139 } | |
140 } | |
141 | |
142 void MouseLockInstance::DidLockMouse(int32_t result) { | |
143 mouse_locked_ = result == PP_OK; | |
144 mouse_movement_.set_x(0); | |
145 mouse_movement_.set_y(0); | |
146 Paint(); | |
147 } | |
148 | |
149 void MouseLockInstance::DidFlush(int32_t result) { | |
150 waiting_for_flush_completion_ = false; | |
151 } | |
152 | |
153 void MouseLockInstance::Paint() { | |
154 if (waiting_for_flush_completion_) { | |
155 return; | |
156 } | |
157 pp::ImageData image = PaintImage(width_, height_); | |
158 if (image.is_null()) { | |
cstefansen
2011/11/10 17:53:03
Log message? (This seems serious.)
der Springer
2011/11/11 19:23:01
Done.
| |
159 return; | |
160 } | |
161 device_context_.ReplaceContents(&image); | |
162 waiting_for_flush_completion_ = true; | |
163 device_context_.Flush( | |
164 callback_factory_.NewRequiredCallback(&MouseLockInstance::DidFlush)); | |
165 } | |
166 | |
167 pp::ImageData MouseLockInstance::PaintImage(int width, int height) { | |
168 pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, | |
169 pp::Size(width, height), false); | |
170 if (image.is_null() || image.data() == NULL) | |
171 return image; | |
172 | |
173 int center_x = width / 2; | |
174 int center_y = height / 2; | |
175 pp::Point vertex(mouse_movement_.x() + center_x, | |
176 mouse_movement_.y() + center_y); | |
177 pp::Point anchor_1; | |
178 pp::Point anchor_2; | |
179 MouseDirection direction = kLeft; | |
180 bool draw_needle = GetDistance(mouse_movement_.x(), mouse_movement_.y(), | |
181 0, 0) > kCentralSpotRadius; | |
182 if (draw_needle) { | |
183 if (abs(mouse_movement_.x()) >= abs(mouse_movement_.y())) { | |
184 anchor_1.set_x(center_x); | |
185 anchor_1.set_y(center_y - kCentralSpotRadius); | |
186 anchor_2.set_x(center_x); | |
187 anchor_2.set_y(center_y + kCentralSpotRadius); | |
188 direction = (mouse_movement_.x() < 0) ? kLeft : kRight; | |
189 if (direction == kLeft) | |
190 anchor_1.swap(anchor_2); | |
191 } else { | |
192 anchor_1.set_x(center_x + kCentralSpotRadius); | |
193 anchor_1.set_y(center_y); | |
194 anchor_2.set_x(center_x - kCentralSpotRadius); | |
195 anchor_2.set_y(center_y); | |
196 direction = (mouse_movement_.y() < 0) ? kUp : kDown; | |
197 if (direction == kUp) | |
198 anchor_1.swap(anchor_2); | |
199 } | |
200 } | |
201 uint32_t foreground_color = mouse_locked_ ? kLockedForegroundColor : | |
202 kUnlockedForegroundColor; | |
203 for (int y = 0; y < image.size().height(); ++y) { | |
cstefansen
2011/11/10 17:53:03
Nit: it may be faster to init the entire canvas to
der Springer
2011/11/11 19:23:01
Factored this routine into three parts and made it
| |
204 for (int x = 0; x < image.size().width(); ++x) { | |
205 if (GetDistance(x, y, center_x, center_y) < kCentralSpotRadius) { | |
206 *image.GetAddr32(pp::Point(x, y)) = foreground_color; | |
207 continue; | |
208 } | |
209 if (draw_needle) { | |
210 bool within_bound_1 = | |
211 ((y - anchor_1.y()) * (vertex.x() - anchor_1.x())) > | |
212 ((vertex.y() - anchor_1.y()) * (x - anchor_1.x())); | |
213 bool within_bound_2 = | |
214 ((y - anchor_2.y()) * (vertex.x() - anchor_2.x())) < | |
215 ((vertex.y() - anchor_2.y()) * (x - anchor_2.x())); | |
216 bool within_bound_3 = | |
217 (direction == kUp && y < center_y) || | |
218 (direction == kDown && y > center_y) || | |
219 (direction == kLeft && x < center_x) || | |
220 (direction == kRight && x > center_x); | |
221 | |
222 if (within_bound_1 && within_bound_2 && within_bound_3) { | |
223 *image.GetAddr32(pp::Point(x, y)) = foreground_color; | |
224 continue; | |
225 } | |
226 } | |
227 *image.GetAddr32(pp::Point(x, y)) = kBackgroundColor; | |
228 } | |
229 } | |
230 | |
231 return image; | |
232 } | |
233 | |
234 void MouseLockInstance::Log(const char* format, ...) { | |
235 va_list args; | |
236 va_start(args, format); | |
237 char buf[512]; | |
238 vsnprintf(buf, sizeof(buf) - 1, format, args); | |
239 buf[sizeof(buf) - 1] = '\0'; | |
240 va_end(args); | |
241 | |
242 pp::Var value(buf); | |
243 PostMessage(value); | |
244 } | |
245 | |
246 } // namespace mouselock | |
247 | |
248 // This object is the global object representing this plugin library as long | |
249 // as it is loaded. | |
250 class MouseLockModule : public pp::Module { | |
251 public: | |
252 MouseLockModule() : pp::Module() {} | |
253 virtual ~MouseLockModule() {} | |
254 | |
255 // Override CreateInstance to create your customized Instance object. | |
256 virtual pp::Instance* CreateInstance(PP_Instance instance) { | |
257 return new mouselock::MouseLockInstance(instance); | |
258 } | |
259 }; | |
260 | |
261 namespace pp { | |
262 | |
263 // Factory function for your specialization of the Module object. | |
264 Module* CreateModule() { | |
265 return new MouseLockModule(); | |
266 } | |
267 | |
268 } // namespace pp | |
269 | |
OLD | NEW |