1df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger/* 2df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * Copyright 2009, The Android Open Source Project 3df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * 4df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * Redistribution and use in source and binary forms, with or without 5df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * modification, are permitted provided that the following conditions 6df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * are met: 7df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * * Redistributions of source code must retain the above copyright 8df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * notice, this list of conditions and the following disclaimer. 9df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * * Redistributions in binary form must reproduce the above copyright 10df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * notice, this list of conditions and the following disclaimer in the 11df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * documentation and/or other materials provided with the distribution. 12df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * 13df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger */ 25df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 26df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger#include "EventPlugin.h" 27df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger#include "android_npapi.h" 28df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 29df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger#include <stdio.h> 30df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger#include <sys/time.h> 31df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger#include <time.h> 32df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger#include <math.h> 33df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger#include <string.h> 34df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 35df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenbergerextern NPNetscapeFuncs* browser; 36df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenbergerextern ANPCanvasInterfaceV0 gCanvasI; 37df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenbergerextern ANPLogInterfaceV0 gLogI; 38df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenbergerextern ANPPaintInterfaceV0 gPaintI; 39df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenbergerextern ANPTypefaceInterfaceV0 gTypefaceI; 40df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 41df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 42df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 430b3a5d65247be1fb79d66af534fa78a94743864fDerek SollenbergerEventPlugin::EventPlugin(NPP inst) : SubPlugin(inst) { } 44df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 450b3a5d65247be1fb79d66af534fa78a94743864fDerek SollenbergerEventPlugin::~EventPlugin() { } 46df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 470b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenbergervoid EventPlugin::drawPlugin(const ANPBitmap& bitmap, const ANPRectI& clip) { 48df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 49b16749e2c60dca69f8b71adf900597bad10adf40Derek Sollenberger gLogI.log(kDebug_ANPLogType, " ------ %p drawing the plugin (%d,%d)", 500b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger inst(), bitmap.width, bitmap.height); 51df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 52df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // get the plugin's dimensions according to the DOM 53df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger PluginObject *obj = (PluginObject*) inst()->pdata; 54df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger const int W = obj->window->width; 55df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger const int H = obj->window->height; 56df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 57df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // compute the current zoom level 580b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger const float zoomFactorW = static_cast<float>(bitmap.width) / W; 590b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger const float zoomFactorH = static_cast<float>(bitmap.height) / H; 60df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 61df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // check to make sure the zoom level is uniform 62df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger if (zoomFactorW + .01 < zoomFactorH && zoomFactorW - .01 > zoomFactorH) 63b16749e2c60dca69f8b71adf900597bad10adf40Derek Sollenberger gLogI.log(kError_ANPLogType, " ------ %p zoom is out of sync (%f,%f)", 64df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger inst(), zoomFactorW, zoomFactorH); 65df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 66df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // scale the variables based on the zoom level 67df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger const int fontSize = (int)(zoomFactorW * 16); 68df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger const int leftMargin = (int)(zoomFactorW * 10); 69df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 700b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger // create and clip a canvas 71df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap); 720b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger 730b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger ANPRectF clipR; 740b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger clipR.left = clip.left; 750b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger clipR.top = clip.top; 760b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger clipR.right = clip.right; 770b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger clipR.bottom = clip.bottom; 780b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger gCanvasI.clipRect(canvas, &clipR); 790b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger 80df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger gCanvasI.drawColor(canvas, 0xFFFFFFFF); 81df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 82df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // configure the paint 83df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger ANPPaint* paint = gPaintI.newPaint(); 84df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger gPaintI.setFlags(paint, gPaintI.getFlags(paint) | kAntiAlias_ANPPaintFlag); 85df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger gPaintI.setColor(paint, 0xFF0000FF); 86df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger gPaintI.setTextSize(paint, fontSize); 87df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 88df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // configure the font 89df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle); 90df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger gPaintI.setTypeface(paint, tf); 91df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger gTypefaceI.unref(tf); 92df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 93df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // retrieve the font metrics 94df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger ANPFontMetrics fm; 95df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger gPaintI.getFontMetrics(paint, &fm); 96df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 97df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // write text on the canvas 98df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger const char c[] = "Browser Test Plugin"; 99df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger gCanvasI.drawText(canvas, c, sizeof(c)-1, leftMargin, -fm.fTop, paint); 100df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 1010b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger // clean up variables 102df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger gPaintI.deletePaint(paint); 103df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger gCanvasI.deleteCanvas(canvas); 104df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger} 105df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 106df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenbergervoid EventPlugin::printToDiv(const char* text, int length) { 107df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // Get the plugin's DOM object 108df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger NPObject* windowObject = NULL; 109df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger browser->getvalue(inst(), NPNVWindowNPObject, &windowObject); 110df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 111df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger if (!windowObject) 112b16749e2c60dca69f8b71adf900597bad10adf40Derek Sollenberger gLogI.log(kError_ANPLogType, " ------ %p Unable to retrieve DOM Window", inst()); 113df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 114df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // create a string (JS code) that is stored in memory allocated by the browser 115df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger const char* jsBegin = "var outputDiv = document.getElementById('eventOutput'); outputDiv.innerHTML += ' "; 116df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger const char* jsEnd = "';"; 117df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 118df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // allocate memory and configure pointers 119df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger int totalLength = strlen(jsBegin) + length + strlen(jsEnd); 120df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger char* beginMem = (char*)browser->memalloc(totalLength); 121df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger char* middleMem = beginMem + strlen(jsBegin); 122df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger char* endMem = middleMem + length; 123df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 124df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // copy into the allocated memory 125df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger memcpy(beginMem, jsBegin, strlen(jsBegin)); 126df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger memcpy(middleMem, text, length); 127df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger memcpy(endMem, jsEnd, strlen(jsEnd)); 128df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 129b16749e2c60dca69f8b71adf900597bad10adf40Derek Sollenberger gLogI.log(kDebug_ANPLogType, "text: %.*s\n", totalLength, (char*)beginMem); 130df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 131df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // execute the javascript in the plugin's DOM object 132df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger NPString script = { (char*)beginMem, totalLength }; 133df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger NPVariant scriptVariant; 134df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger if (!browser->evaluate(inst(), windowObject, &script, &scriptVariant)) 135b16749e2c60dca69f8b71adf900597bad10adf40Derek Sollenberger gLogI.log(kError_ANPLogType, " ------ %p Unable to eval the JS.", inst()); 136df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 137df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger // free the memory allocated within the browser 138df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger browser->memfree(beginMem); 139df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger} 140df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger 141ccee91085913ccb486b063616afae13b53b2e92bBen Murdochint16_t EventPlugin::handleEvent(const ANPEvent* evt) { 142df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger switch (evt->eventType) { 1430b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger 1440b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger case kDraw_ANPEventType: { 1450b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger switch (evt->data.draw.model) { 1460b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger case kBitmap_ANPDrawingModel: 1470b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger drawPlugin(evt->data.draw.data.bitmap, evt->data.draw.clip); 148df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger return 1; 1490b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger default: 1500b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger break; // unknown drawing model 151df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger } 1520b3a5d65247be1fb79d66af534fa78a94743864fDerek Sollenberger } 153df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger case kLifecycle_ANPEventType: 154df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger switch (evt->data.lifecycle.action) { 155df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger case kOnLoad_ANPLifecycleAction: { 156df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger char msg[] = "lifecycle-onLoad"; 157df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger printToDiv(msg, strlen(msg)); 158df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger break; 159df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger } 160df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger case kGainFocus_ANPLifecycleAction: { 161df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger char msg[] = "lifecycle-gainFocus"; 162df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger printToDiv(msg, strlen(msg)); 163df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger break; 164df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger } 165df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger case kLoseFocus_ANPLifecycleAction: { 166df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger char msg[] = "lifecycle-loseFocus"; 167df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger printToDiv(msg, strlen(msg)); 168df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger break; 169df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger } 170df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger } 171df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger return 1; 172df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger case kTouch_ANPEventType: 173b16749e2c60dca69f8b71adf900597bad10adf40Derek Sollenberger gLogI.log(kError_ANPLogType, " ------ %p the plugin did not request touch events", inst()); 174df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger break; 175df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger case kKey_ANPEventType: 176b16749e2c60dca69f8b71adf900597bad10adf40Derek Sollenberger gLogI.log(kError_ANPLogType, " ------ %p the plugin did not request key events", inst()); 177df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger break; 178df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger default: 179df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger break; 180df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger } 181df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger return 0; // unknown or unhandled event 182df8a3f31d871db25e952972c2eb346a71186e9e3Derek Sollenberger} 183