15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdarg.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include <cmath> 9b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include <cstdlib> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "mouse_lock.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef min 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef max 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef PostMessage 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Indicate the direction of the mouse location relative to the center of the 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// view. These values are used to determine which 2D quadrant the needle lies 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef enum { 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kLeft = 0, 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kRight = 1, 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kUp = 2, 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kDown = 3 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} MouseDirection; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kCentralSpotRadius = 5; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32_t kReturnKeyCode = 13; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32_t kBackgroundColor = 0xff606060; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint32_t kForegroundColor = 0xfff08080; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MouseLockInstance::~MouseLockInstance() { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(background_scanline_); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_scanline_ = NULL; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MouseLockInstance::Init(uint32_t argc, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* argn[], 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* argv[]) { 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_KEYBOARD); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MouseLockInstance::HandleInputEvent(const pp::InputEvent& event) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (event.GetType()) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEDOWN: { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mouse_locked_) { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UnlockMouse(); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LockMouse( 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback_factory_.NewCallback(&MouseLockInstance::DidLockMouse)); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEMOVE: { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::MouseInputEvent mouse_event(event); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_movement_ = mouse_event.GetMovement(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Paint(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_KEYDOWN: { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::KeyboardInputEvent key_event(event); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Switch in and out of fullscreen when 'Enter' is hit 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key_event.GetKeyCode() == kReturnKeyCode) { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Ignore switch if in transition 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_context_bound_) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (fullscreen_.IsFullscreen()) { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fullscreen_.SetFullscreen(false)) { 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log("Could not leave fullscreen mode\n"); 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_context_bound_ = false; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fullscreen_.SetFullscreen(true)) { 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log("Could not enter fullscreen mode\n"); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_context_bound_ = false; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEUP: 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEENTER: 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSELEAVE: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_WHEEL: 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_RAWKEYDOWN: 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_KEYUP: 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_CHAR: 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_CONTEXTMENU: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START: 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_IME_TEXT: 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_UNDEFINED: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_TOUCHSTART: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_TOUCHMOVE: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_TOUCHEND: 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_TOUCHCANCEL: 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MouseLockInstance::DidChangeView(const pp::View& view) { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // DidChangeView can get called for many reasons, so we only want to 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // rebuild the device context if we really need to. 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((size_ == view.GetRect().size()) && 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (was_fullscreen_ == view.IsFullscreen()) && is_context_bound_) { 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Log("DidChangeView SKIP %d,%d FULL=%s CTX Bound=%s", 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) view.GetRect().width(), 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) view.GetRect().height(), 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) view.IsFullscreen() ? "true" : "false", 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_context_bound_ ? "true" : "false"); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log("DidChangeView DO %d,%d FULL=%s CTX Bound=%s", 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) view.GetRect().width(), 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) view.GetRect().height(), 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view.IsFullscreen() ? "true" : "false", 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_context_bound_ ? "true" : "false"); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_ = view.GetRect().size(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_context_ = pp::Graphics2D(this, size_, false); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_for_flush_completion_ = false; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_context_bound_ = BindGraphics(device_context_); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_context_bound_) { 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log("Could not bind to 2D context\n."); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log("Bound to 2D context size %d,%d.\n", size_.width(), size_.height()); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a scanline for fill. 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete[] background_scanline_; 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) background_scanline_ = new uint32_t[size_.width()]; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t* bg_pixel = background_scanline_; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int x = 0; x < size_.width(); ++x) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bg_pixel++ = kBackgroundColor; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remember if we are fullscreen or not 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) was_fullscreen_ = view.IsFullscreen(); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Paint this context 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Paint(); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MouseLockInstance::MouseLockLost() { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mouse_locked_) { 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log("Mouselock unlocked.\n"); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_locked_ = false; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Paint(); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MouseLockInstance::DidLockMouse(int32_t result) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_locked_ = result == PP_OK; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (result != PP_OK) { 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log("Mouselock failed with failed with error number %d.\n", result); 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_movement_.set_x(0); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_movement_.set_y(0); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Paint(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MouseLockInstance::DidFlush(int32_t result) { 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result != 0) 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Log("Flushed failed with error number %d.\n", result); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_for_flush_completion_ = false; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MouseLockInstance::Paint() { 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we are already waiting to paint... 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (waiting_for_flush_completion_) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::ImageData image = PaintImage(size_); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image.is_null()) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Log("Could not create image data\n"); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_context_.ReplaceContents(&image); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_for_flush_completion_ = true; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_context_.Flush( 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_factory_.NewCallback(&MouseLockInstance::DidFlush)); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pp::ImageData MouseLockInstance::PaintImage(const pp::Size& size) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image.is_null() || image.data() == NULL) { 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log("Skipping image.\n"); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return image; 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClearToBackground(&image); 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DrawCenterSpot(&image, kForegroundColor); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DrawNeedle(&image, kForegroundColor); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return image; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MouseLockInstance::ClearToBackground(pp::ImageData* image) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image == NULL) { 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log("ClearToBackground with NULL image."); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (background_scanline_ == NULL) { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Log("ClearToBackground with no scanline."); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int image_height = image->size().height(); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int image_width = image->size().width(); 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int y = 0; y < image_height; ++y) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t* scanline = image->GetAddr32(pp::Point(0, y)); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(scanline, 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_scanline_, 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_width * sizeof(*background_scanline_)); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MouseLockInstance::DrawCenterSpot(pp::ImageData* image, 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t spot_color) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image == NULL) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Log("DrawCenterSpot with NULL image"); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw the center spot. The ROI is bounded by the size of the spot, plus 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one pixel. 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int center_x = image->size().width() / 2; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int center_y = image->size().height() / 2; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int region_of_interest_radius = kCentralSpotRadius + 1; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Point left_top(std::max(0, center_x - region_of_interest_radius), 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(0, center_y - region_of_interest_radius)); 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::Point right_bottom( 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::min(image->size().width(), center_x + region_of_interest_radius), 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::min(image->size().height(), center_y + region_of_interest_radius)); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int y = left_top.y(); y < right_bottom.y(); ++y) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int x = left_top.x(); x < right_bottom.x(); ++x) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetDistance(x, y, center_x, center_y) < kCentralSpotRadius) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *image->GetAddr32(pp::Point(x, y)) = spot_color; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MouseLockInstance::DrawNeedle(pp::ImageData* image, 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t needle_color) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image == NULL) { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Log("DrawNeedle with NULL image"); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetDistance(mouse_movement_.x(), mouse_movement_.y(), 0, 0) <= 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCentralSpotRadius) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int abs_mouse_x = std::abs(mouse_movement_.x()); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int abs_mouse_y = std::abs(mouse_movement_.y()); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int center_x = image->size().width() / 2; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int center_y = image->size().height() / 2; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Point vertex(mouse_movement_.x() + center_x, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_movement_.y() + center_y); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Point anchor_1; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Point anchor_2; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MouseDirection direction = kLeft; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (abs_mouse_x >= abs_mouse_y) { 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) anchor_1.set_x(center_x); 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) anchor_1.set_y(center_y - kCentralSpotRadius); 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) anchor_2.set_x(center_x); 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) anchor_2.set_y(center_y + kCentralSpotRadius); 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) direction = (mouse_movement_.x() < 0) ? kLeft : kRight; 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (direction == kLeft) 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) anchor_1.swap(anchor_2); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) anchor_1.set_x(center_x + kCentralSpotRadius); 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) anchor_1.set_y(center_y); 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) anchor_2.set_x(center_x - kCentralSpotRadius); 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) anchor_2.set_y(center_y); 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) direction = (mouse_movement_.y() < 0) ? kUp : kDown; 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (direction == kUp) 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) anchor_1.swap(anchor_2); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Point left_top(std::max(0, center_x - abs_mouse_x), 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(0, center_y - abs_mouse_y)); 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pp::Point right_bottom( 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::min(image->size().width(), center_x + abs_mouse_x), 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::min(image->size().height(), center_y + abs_mouse_y)); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int y = left_top.y(); y < right_bottom.y(); ++y) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int x = left_top.x(); x < right_bottom.x(); ++x) { 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool within_bound_1 = ((y - anchor_1.y()) * (vertex.x() - anchor_1.x())) > 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ((vertex.y() - anchor_1.y()) * (x - anchor_1.x())); 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool within_bound_2 = ((y - anchor_2.y()) * (vertex.x() - anchor_2.x())) < 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ((vertex.y() - anchor_2.y()) * (x - anchor_2.x())); 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool within_bound_3 = (direction == kUp && y < center_y) || 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (direction == kDown && y > center_y) || 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (direction == kLeft && x < center_x) || 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (direction == kRight && x > center_x); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (within_bound_1 && within_bound_2 && within_bound_3) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *image->GetAddr32(pp::Point(x, y)) = needle_color; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MouseLockInstance::Log(const char* format, ...) { 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static PPB_Console* console = 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (PPB_Console*)pp::Module::Get()->GetBrowserInterface( 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PPB_CONSOLE_INTERFACE); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (NULL == console) 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_list args; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_start(args, format); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[512]; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vsnprintf(buf, sizeof(buf) - 1, format, args); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[sizeof(buf) - 1] = '\0'; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_end(args); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Var value(buf); 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) console->Log(pp_instance(), PP_LOGLEVEL_ERROR, value.pp_var()); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This object is the global object representing this plugin library as long 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as it is loaded. 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MouseLockModule : public pp::Module { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MouseLockModule() : pp::Module() {} 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~MouseLockModule() {} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Override CreateInstance to create your customized Instance object. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual pp::Instance* CreateInstance(PP_Instance instance) { 355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return new MouseLockInstance(instance); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace pp { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Factory function for your specialization of the Module object. 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Module* CreateModule() { return new MouseLockModule(); } 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace pp 365