Chromium Code Reviews
|
| 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 |