1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/plugins/test/testplugin/nptest_macosx.mm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,317 @@ 1.4 +/* ***** BEGIN LICENSE BLOCK ***** 1.5 + * 1.6 + * Copyright (c) 2008, Mozilla Corporation 1.7 + * All rights reserved. 1.8 + * 1.9 + * Redistribution and use in source and binary forms, with or without 1.10 + * modification, are permitted provided that the following conditions are met: 1.11 + * 1.12 + * * Redistributions of source code must retain the above copyright notice, this 1.13 + * list of conditions and the following disclaimer. 1.14 + * * Redistributions in binary form must reproduce the above copyright notice, 1.15 + * this list of conditions and the following disclaimer in the documentation 1.16 + * and/or other materials provided with the distribution. 1.17 + * * Neither the name of the Mozilla Corporation nor the names of its 1.18 + * contributors may be used to endorse or promote products derived from this 1.19 + * software without specific prior written permission. 1.20 + * 1.21 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 1.22 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1.23 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1.24 + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 1.25 + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1.26 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 1.27 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 1.28 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.29 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1.30 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.31 + * 1.32 + * Contributor(s): 1.33 + * Josh Aas <josh@mozilla.com> 1.34 + * 1.35 + * ***** END LICENSE BLOCK ***** */ 1.36 + 1.37 +#include "nptest_platform.h" 1.38 +#include "nsAlgorithm.h" 1.39 +#include <CoreServices/CoreServices.h> 1.40 +#include <algorithm> 1.41 + 1.42 +using namespace std; 1.43 + 1.44 +bool 1.45 +pluginSupportsWindowMode() 1.46 +{ 1.47 + return false; 1.48 +} 1.49 + 1.50 +bool 1.51 +pluginSupportsWindowlessMode() 1.52 +{ 1.53 + return true; 1.54 +} 1.55 + 1.56 +bool 1.57 +pluginSupportsAsyncBitmapDrawing() 1.58 +{ 1.59 + return false; 1.60 +} 1.61 + 1.62 +NPError 1.63 +pluginInstanceInit(InstanceData* instanceData) 1.64 +{ 1.65 + NPP npp = instanceData->npp; 1.66 + 1.67 + NPBool supportsCoreGraphics = false; 1.68 + if ((NPN_GetValue(npp, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) == NPERR_NO_ERROR) && 1.69 + supportsCoreGraphics) { 1.70 + NPN_SetValue(npp, NPPVpluginDrawingModel, (void*)NPDrawingModelCoreGraphics); 1.71 + } else { 1.72 + printf("CoreGraphics drawing model not supported, can't create a plugin instance.\n"); 1.73 + return NPERR_INCOMPATIBLE_VERSION_ERROR; 1.74 + } 1.75 + 1.76 + NPBool supportsCocoaEvents = false; 1.77 + if ((NPN_GetValue(npp, NPNVsupportsCocoaBool, &supportsCocoaEvents) == NPERR_NO_ERROR) && 1.78 + supportsCocoaEvents) { 1.79 + NPN_SetValue(npp, NPPVpluginEventModel, (void*)NPEventModelCocoa); 1.80 + instanceData->eventModel = NPEventModelCocoa; 1.81 + } else { 1.82 + printf("Cocoa event model not supported, can't create a plugin instance.\n"); 1.83 + return NPERR_INCOMPATIBLE_VERSION_ERROR; 1.84 + } 1.85 + 1.86 + return NPERR_NO_ERROR; 1.87 +} 1.88 + 1.89 +void 1.90 +pluginInstanceShutdown(InstanceData* instanceData) 1.91 +{ 1.92 +} 1.93 + 1.94 +static bool 1.95 +RectEquals(const NPRect& r1, const NPRect& r2) 1.96 +{ 1.97 + return r1.left == r2.left && r1.top == r2.top && 1.98 + r1.right == r2.right && r1.bottom == r2.bottom; 1.99 +} 1.100 + 1.101 +void 1.102 +pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow) 1.103 +{ 1.104 + // Ugh. Due to a terrible Gecko bug, we have to ignore position changes 1.105 + // when the clip rect doesn't change; the position can be wrong 1.106 + // when set by a path other than nsObjectFrame::FixUpPluginWindow. 1.107 + int32_t oldX = instanceData->window.x; 1.108 + int32_t oldY = instanceData->window.y; 1.109 + bool clipChanged = 1.110 + !RectEquals(instanceData->window.clipRect, newWindow->clipRect); 1.111 + instanceData->window = *newWindow; 1.112 + if (!clipChanged) { 1.113 + instanceData->window.x = oldX; 1.114 + instanceData->window.y = oldY; 1.115 + } 1.116 +} 1.117 + 1.118 +void 1.119 +pluginWidgetInit(InstanceData* instanceData, void* oldWindow) 1.120 +{ 1.121 + // Should never be called since we don't support window mode 1.122 +} 1.123 + 1.124 +static void 1.125 +GetColorsFromRGBA(uint32_t rgba, float* r, float* g, float* b, float* a) 1.126 +{ 1.127 + *b = (rgba & 0xFF) / 255.0; 1.128 + *g = ((rgba & 0xFF00) >> 8) / 255.0; 1.129 + *r = ((rgba & 0xFF0000) >> 16) / 255.0; 1.130 + *a = ((rgba & 0xFF000000) >> 24) / 255.0; 1.131 +} 1.132 + 1.133 +static void 1.134 +pluginDraw(InstanceData* instanceData, NPCocoaEvent* event) 1.135 +{ 1.136 + if (!instanceData) 1.137 + return; 1.138 + 1.139 + notifyDidPaint(instanceData); 1.140 + 1.141 + NPP npp = instanceData->npp; 1.142 + if (!npp) 1.143 + return; 1.144 + 1.145 + const char* uaString = NPN_UserAgent(npp); 1.146 + if (!uaString) 1.147 + return; 1.148 + 1.149 + NPWindow window = instanceData->window; 1.150 + 1.151 + CGContextRef cgContext = event->data.draw.context; 1.152 + 1.153 + float windowWidth = window.width; 1.154 + float windowHeight = window.height; 1.155 + 1.156 + switch(instanceData->scriptableObject->drawMode) { 1.157 + case DM_DEFAULT: { 1.158 + CFStringRef uaCFString = CFStringCreateWithCString(kCFAllocatorDefault, uaString, kCFStringEncodingASCII); 1.159 + // save the cgcontext gstate 1.160 + CGContextSaveGState(cgContext); 1.161 + 1.162 + // we get a flipped context 1.163 + CGContextTranslateCTM(cgContext, 0.0, windowHeight); 1.164 + CGContextScaleCTM(cgContext, 1.0, -1.0); 1.165 + 1.166 + // draw a gray background for the plugin 1.167 + CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight)); 1.168 + CGContextSetGrayFillColor(cgContext, 0.5, 1.0); 1.169 + CGContextDrawPath(cgContext, kCGPathFill); 1.170 + 1.171 + // draw a black frame around the plugin 1.172 + CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight)); 1.173 + CGContextSetGrayStrokeColor(cgContext, 0.0, 1.0); 1.174 + CGContextSetLineWidth(cgContext, 6.0); 1.175 + CGContextStrokePath(cgContext); 1.176 + 1.177 + // draw the UA string using Core Text 1.178 + CGContextSetTextMatrix(cgContext, CGAffineTransformIdentity); 1.179 + 1.180 + // Initialize a rectangular path. 1.181 + CGMutablePathRef path = CGPathCreateMutable(); 1.182 + CGRect bounds = CGRectMake(10.0, 10.0, std::max(0.0, windowWidth - 20.0), 1.183 + std::max(0.0, windowHeight - 20.0)); 1.184 + CGPathAddRect(path, NULL, bounds); 1.185 + 1.186 + // Initialize an attributed string. 1.187 + CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); 1.188 + CFAttributedStringReplaceString(attrString, CFRangeMake(0, 0), uaCFString); 1.189 + 1.190 + // Create a color and add it as an attribute to the string. 1.191 + CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 1.192 + CGFloat components[] = { 0.0, 0.0, 0.0, 1.0 }; 1.193 + CGColorRef red = CGColorCreate(rgbColorSpace, components); 1.194 + CGColorSpaceRelease(rgbColorSpace); 1.195 + CFAttributedStringSetAttribute(attrString, CFRangeMake(0, 50), kCTForegroundColorAttributeName, red); 1.196 + 1.197 + // Create the framesetter with the attributed string. 1.198 + CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString); 1.199 + CFRelease(attrString); 1.200 + 1.201 + // Create the frame and draw it into the graphics context 1.202 + CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); 1.203 + CFRelease(framesetter); 1.204 + if (frame) { 1.205 + CTFrameDraw(frame, cgContext); 1.206 + CFRelease(frame); 1.207 + } 1.208 + 1.209 + // restore the cgcontext gstate 1.210 + CGContextRestoreGState(cgContext); 1.211 + break; 1.212 + } 1.213 + case DM_SOLID_COLOR: { 1.214 + // save the cgcontext gstate 1.215 + CGContextSaveGState(cgContext); 1.216 + 1.217 + // we get a flipped context 1.218 + CGContextTranslateCTM(cgContext, 0.0, windowHeight); 1.219 + CGContextScaleCTM(cgContext, 1.0, -1.0); 1.220 + 1.221 + // draw a solid background for the plugin 1.222 + CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight)); 1.223 + 1.224 + float r,g,b,a; 1.225 + GetColorsFromRGBA(instanceData->scriptableObject->drawColor, &r, &g, &b, &a); 1.226 + CGContextSetRGBFillColor(cgContext, r, g, b, a); 1.227 + CGContextDrawPath(cgContext, kCGPathFill); 1.228 + 1.229 + // restore the cgcontext gstate 1.230 + CGContextRestoreGState(cgContext); 1.231 + break; 1.232 + } 1.233 + } 1.234 +} 1.235 + 1.236 +int16_t 1.237 +pluginHandleEvent(InstanceData* instanceData, void* event) 1.238 +{ 1.239 + NPCocoaEvent* cocoaEvent = (NPCocoaEvent*)event; 1.240 + if (!cocoaEvent) 1.241 + return kNPEventNotHandled; 1.242 + 1.243 + switch (cocoaEvent->type) { 1.244 + case NPCocoaEventDrawRect: 1.245 + pluginDraw(instanceData, cocoaEvent); 1.246 + break; 1.247 + case NPCocoaEventMouseDown: 1.248 + case NPCocoaEventMouseUp: 1.249 + case NPCocoaEventMouseMoved: 1.250 + instanceData->lastMouseX = (int32_t)cocoaEvent->data.mouse.pluginX; 1.251 + instanceData->lastMouseY = (int32_t)cocoaEvent->data.mouse.pluginY; 1.252 + if (cocoaEvent->type == NPCocoaEventMouseUp) { 1.253 + instanceData->mouseUpEventCount++; 1.254 + } 1.255 + break; 1.256 + case NPCocoaEventWindowFocusChanged: 1.257 + instanceData->topLevelWindowActivationState = cocoaEvent->data.focus.hasFocus ? 1.258 + ACTIVATION_STATE_ACTIVATED : ACTIVATION_STATE_DEACTIVATED; 1.259 + instanceData->topLevelWindowActivationEventCount = instanceData->topLevelWindowActivationEventCount + 1; 1.260 + break; 1.261 + case NPCocoaEventFocusChanged: 1.262 + instanceData->focusState = cocoaEvent->data.focus.hasFocus ? 1.263 + ACTIVATION_STATE_ACTIVATED : ACTIVATION_STATE_DEACTIVATED; 1.264 + instanceData->focusEventCount = instanceData->focusEventCount + 1; 1.265 + break; 1.266 + default: 1.267 + return kNPEventNotHandled; 1.268 + } 1.269 + 1.270 + return kNPEventHandled; 1.271 +} 1.272 + 1.273 +int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge) 1.274 +{ 1.275 + NPWindow* w = &instanceData->window; 1.276 + switch (edge) { 1.277 + case EDGE_LEFT: 1.278 + return w->x; 1.279 + case EDGE_TOP: 1.280 + return w->y; 1.281 + case EDGE_RIGHT: 1.282 + return w->x + w->width; 1.283 + case EDGE_BOTTOM: 1.284 + return w->y + w->height; 1.285 + } 1.286 + return NPTEST_INT32_ERROR; 1.287 +} 1.288 + 1.289 +int32_t pluginGetClipRegionRectCount(InstanceData* instanceData) 1.290 +{ 1.291 + return 1; 1.292 +} 1.293 + 1.294 +int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData, 1.295 + int32_t rectIndex, RectEdge edge) 1.296 +{ 1.297 + if (rectIndex != 0) 1.298 + return NPTEST_INT32_ERROR; 1.299 + 1.300 + // We have to add the Cocoa titlebar height here since the clip rect 1.301 + // is being returned relative to that 1.302 + static const int COCOA_TITLEBAR_HEIGHT = 22; 1.303 + 1.304 + NPWindow* w = &instanceData->window; 1.305 + switch (edge) { 1.306 + case EDGE_LEFT: 1.307 + return w->clipRect.left; 1.308 + case EDGE_TOP: 1.309 + return w->clipRect.top + COCOA_TITLEBAR_HEIGHT; 1.310 + case EDGE_RIGHT: 1.311 + return w->clipRect.right; 1.312 + case EDGE_BOTTOM: 1.313 + return w->clipRect.bottom + COCOA_TITLEBAR_HEIGHT; 1.314 + } 1.315 + return NPTEST_INT32_ERROR; 1.316 +} 1.317 + 1.318 +void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error) 1.319 +{ 1.320 +}