dom/plugins/test/testplugin/nptest_macosx.mm

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:9099dd5713a9
1 /* ***** BEGIN LICENSE BLOCK *****
2 *
3 * Copyright (c) 2008, Mozilla Corporation
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * * Neither the name of the Mozilla Corporation nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contributor(s):
30 * Josh Aas <josh@mozilla.com>
31 *
32 * ***** END LICENSE BLOCK ***** */
33
34 #include "nptest_platform.h"
35 #include "nsAlgorithm.h"
36 #include <CoreServices/CoreServices.h>
37 #include <algorithm>
38
39 using namespace std;
40
41 bool
42 pluginSupportsWindowMode()
43 {
44 return false;
45 }
46
47 bool
48 pluginSupportsWindowlessMode()
49 {
50 return true;
51 }
52
53 bool
54 pluginSupportsAsyncBitmapDrawing()
55 {
56 return false;
57 }
58
59 NPError
60 pluginInstanceInit(InstanceData* instanceData)
61 {
62 NPP npp = instanceData->npp;
63
64 NPBool supportsCoreGraphics = false;
65 if ((NPN_GetValue(npp, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) == NPERR_NO_ERROR) &&
66 supportsCoreGraphics) {
67 NPN_SetValue(npp, NPPVpluginDrawingModel, (void*)NPDrawingModelCoreGraphics);
68 } else {
69 printf("CoreGraphics drawing model not supported, can't create a plugin instance.\n");
70 return NPERR_INCOMPATIBLE_VERSION_ERROR;
71 }
72
73 NPBool supportsCocoaEvents = false;
74 if ((NPN_GetValue(npp, NPNVsupportsCocoaBool, &supportsCocoaEvents) == NPERR_NO_ERROR) &&
75 supportsCocoaEvents) {
76 NPN_SetValue(npp, NPPVpluginEventModel, (void*)NPEventModelCocoa);
77 instanceData->eventModel = NPEventModelCocoa;
78 } else {
79 printf("Cocoa event model not supported, can't create a plugin instance.\n");
80 return NPERR_INCOMPATIBLE_VERSION_ERROR;
81 }
82
83 return NPERR_NO_ERROR;
84 }
85
86 void
87 pluginInstanceShutdown(InstanceData* instanceData)
88 {
89 }
90
91 static bool
92 RectEquals(const NPRect& r1, const NPRect& r2)
93 {
94 return r1.left == r2.left && r1.top == r2.top &&
95 r1.right == r2.right && r1.bottom == r2.bottom;
96 }
97
98 void
99 pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow)
100 {
101 // Ugh. Due to a terrible Gecko bug, we have to ignore position changes
102 // when the clip rect doesn't change; the position can be wrong
103 // when set by a path other than nsObjectFrame::FixUpPluginWindow.
104 int32_t oldX = instanceData->window.x;
105 int32_t oldY = instanceData->window.y;
106 bool clipChanged =
107 !RectEquals(instanceData->window.clipRect, newWindow->clipRect);
108 instanceData->window = *newWindow;
109 if (!clipChanged) {
110 instanceData->window.x = oldX;
111 instanceData->window.y = oldY;
112 }
113 }
114
115 void
116 pluginWidgetInit(InstanceData* instanceData, void* oldWindow)
117 {
118 // Should never be called since we don't support window mode
119 }
120
121 static void
122 GetColorsFromRGBA(uint32_t rgba, float* r, float* g, float* b, float* a)
123 {
124 *b = (rgba & 0xFF) / 255.0;
125 *g = ((rgba & 0xFF00) >> 8) / 255.0;
126 *r = ((rgba & 0xFF0000) >> 16) / 255.0;
127 *a = ((rgba & 0xFF000000) >> 24) / 255.0;
128 }
129
130 static void
131 pluginDraw(InstanceData* instanceData, NPCocoaEvent* event)
132 {
133 if (!instanceData)
134 return;
135
136 notifyDidPaint(instanceData);
137
138 NPP npp = instanceData->npp;
139 if (!npp)
140 return;
141
142 const char* uaString = NPN_UserAgent(npp);
143 if (!uaString)
144 return;
145
146 NPWindow window = instanceData->window;
147
148 CGContextRef cgContext = event->data.draw.context;
149
150 float windowWidth = window.width;
151 float windowHeight = window.height;
152
153 switch(instanceData->scriptableObject->drawMode) {
154 case DM_DEFAULT: {
155 CFStringRef uaCFString = CFStringCreateWithCString(kCFAllocatorDefault, uaString, kCFStringEncodingASCII);
156 // save the cgcontext gstate
157 CGContextSaveGState(cgContext);
158
159 // we get a flipped context
160 CGContextTranslateCTM(cgContext, 0.0, windowHeight);
161 CGContextScaleCTM(cgContext, 1.0, -1.0);
162
163 // draw a gray background for the plugin
164 CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
165 CGContextSetGrayFillColor(cgContext, 0.5, 1.0);
166 CGContextDrawPath(cgContext, kCGPathFill);
167
168 // draw a black frame around the plugin
169 CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
170 CGContextSetGrayStrokeColor(cgContext, 0.0, 1.0);
171 CGContextSetLineWidth(cgContext, 6.0);
172 CGContextStrokePath(cgContext);
173
174 // draw the UA string using Core Text
175 CGContextSetTextMatrix(cgContext, CGAffineTransformIdentity);
176
177 // Initialize a rectangular path.
178 CGMutablePathRef path = CGPathCreateMutable();
179 CGRect bounds = CGRectMake(10.0, 10.0, std::max(0.0, windowWidth - 20.0),
180 std::max(0.0, windowHeight - 20.0));
181 CGPathAddRect(path, NULL, bounds);
182
183 // Initialize an attributed string.
184 CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
185 CFAttributedStringReplaceString(attrString, CFRangeMake(0, 0), uaCFString);
186
187 // Create a color and add it as an attribute to the string.
188 CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
189 CGFloat components[] = { 0.0, 0.0, 0.0, 1.0 };
190 CGColorRef red = CGColorCreate(rgbColorSpace, components);
191 CGColorSpaceRelease(rgbColorSpace);
192 CFAttributedStringSetAttribute(attrString, CFRangeMake(0, 50), kCTForegroundColorAttributeName, red);
193
194 // Create the framesetter with the attributed string.
195 CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
196 CFRelease(attrString);
197
198 // Create the frame and draw it into the graphics context
199 CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
200 CFRelease(framesetter);
201 if (frame) {
202 CTFrameDraw(frame, cgContext);
203 CFRelease(frame);
204 }
205
206 // restore the cgcontext gstate
207 CGContextRestoreGState(cgContext);
208 break;
209 }
210 case DM_SOLID_COLOR: {
211 // save the cgcontext gstate
212 CGContextSaveGState(cgContext);
213
214 // we get a flipped context
215 CGContextTranslateCTM(cgContext, 0.0, windowHeight);
216 CGContextScaleCTM(cgContext, 1.0, -1.0);
217
218 // draw a solid background for the plugin
219 CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
220
221 float r,g,b,a;
222 GetColorsFromRGBA(instanceData->scriptableObject->drawColor, &r, &g, &b, &a);
223 CGContextSetRGBFillColor(cgContext, r, g, b, a);
224 CGContextDrawPath(cgContext, kCGPathFill);
225
226 // restore the cgcontext gstate
227 CGContextRestoreGState(cgContext);
228 break;
229 }
230 }
231 }
232
233 int16_t
234 pluginHandleEvent(InstanceData* instanceData, void* event)
235 {
236 NPCocoaEvent* cocoaEvent = (NPCocoaEvent*)event;
237 if (!cocoaEvent)
238 return kNPEventNotHandled;
239
240 switch (cocoaEvent->type) {
241 case NPCocoaEventDrawRect:
242 pluginDraw(instanceData, cocoaEvent);
243 break;
244 case NPCocoaEventMouseDown:
245 case NPCocoaEventMouseUp:
246 case NPCocoaEventMouseMoved:
247 instanceData->lastMouseX = (int32_t)cocoaEvent->data.mouse.pluginX;
248 instanceData->lastMouseY = (int32_t)cocoaEvent->data.mouse.pluginY;
249 if (cocoaEvent->type == NPCocoaEventMouseUp) {
250 instanceData->mouseUpEventCount++;
251 }
252 break;
253 case NPCocoaEventWindowFocusChanged:
254 instanceData->topLevelWindowActivationState = cocoaEvent->data.focus.hasFocus ?
255 ACTIVATION_STATE_ACTIVATED : ACTIVATION_STATE_DEACTIVATED;
256 instanceData->topLevelWindowActivationEventCount = instanceData->topLevelWindowActivationEventCount + 1;
257 break;
258 case NPCocoaEventFocusChanged:
259 instanceData->focusState = cocoaEvent->data.focus.hasFocus ?
260 ACTIVATION_STATE_ACTIVATED : ACTIVATION_STATE_DEACTIVATED;
261 instanceData->focusEventCount = instanceData->focusEventCount + 1;
262 break;
263 default:
264 return kNPEventNotHandled;
265 }
266
267 return kNPEventHandled;
268 }
269
270 int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge)
271 {
272 NPWindow* w = &instanceData->window;
273 switch (edge) {
274 case EDGE_LEFT:
275 return w->x;
276 case EDGE_TOP:
277 return w->y;
278 case EDGE_RIGHT:
279 return w->x + w->width;
280 case EDGE_BOTTOM:
281 return w->y + w->height;
282 }
283 return NPTEST_INT32_ERROR;
284 }
285
286 int32_t pluginGetClipRegionRectCount(InstanceData* instanceData)
287 {
288 return 1;
289 }
290
291 int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData,
292 int32_t rectIndex, RectEdge edge)
293 {
294 if (rectIndex != 0)
295 return NPTEST_INT32_ERROR;
296
297 // We have to add the Cocoa titlebar height here since the clip rect
298 // is being returned relative to that
299 static const int COCOA_TITLEBAR_HEIGHT = 22;
300
301 NPWindow* w = &instanceData->window;
302 switch (edge) {
303 case EDGE_LEFT:
304 return w->clipRect.left;
305 case EDGE_TOP:
306 return w->clipRect.top + COCOA_TITLEBAR_HEIGHT;
307 case EDGE_RIGHT:
308 return w->clipRect.right;
309 case EDGE_BOTTOM:
310 return w->clipRect.bottom + COCOA_TITLEBAR_HEIGHT;
311 }
312 return NPTEST_INT32_ERROR;
313 }
314
315 void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error)
316 {
317 }

mercurial