• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in
3 consideration of your agreement to the following terms, and your use, installation,
4 modification or redistribution of this Apple software constitutes acceptance of these
5 terms.  If you do not agree with these terms, please do not use, install, modify or
6 redistribute this Apple software.
7
8 In consideration of your agreement to abide by the following terms, and subject to these
9 terms, Apple grants you a personal, non-exclusive license, under Apple’s copyrights in
10 this original Apple software (the "Apple Software"), to use, reproduce, modify and
11 redistribute the Apple Software, with or without modifications, in source and/or binary
12 forms; provided that if you redistribute the Apple Software in its entirety and without
13 modifications, you must retain this notice and the following text and disclaimers in all
14 such redistributions of the Apple Software.  Neither the name, trademarks, service marks
15 or logos of Apple Computer, Inc. may be used to endorse or promote products derived from
16 the Apple Software without specific prior written permission from Apple. Except as expressly
17 stated in this notice, no other rights or licenses, express or implied, are granted by Apple
18 herein, including but not limited to any patent rights that may be infringed by your
19 derivative works or by other works in which the Apple Software may be incorporated.
20
21 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO WARRANTIES,
22 EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
23 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS
24 USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
25
26 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL
27 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE,
29 REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND
30 WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
31 OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#import <WebKit/npapi.h>
35#import <WebKit/npfunctions.h>
36#import <WebKit/npruntime.h>
37
38#import <Cocoa/Cocoa.h>
39
40#import "MenuHandler.h"
41
42// Browser function table
43static NPNetscapeFuncs* browser;
44
45// Structure for per-instance storage
46typedef struct PluginObject
47{
48    NPP npp;
49
50    NPWindow window;
51
52    NSString *string;
53    bool hasFocus;
54    bool mouseIsInsidePlugin;
55
56    MenuHandler *menuHandler;
57} PluginObject;
58
59NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved);
60NPError NPP_Destroy(NPP instance, NPSavedData** save);
61NPError NPP_SetWindow(NPP instance, NPWindow* window);
62NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype);
63NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason);
64int32_t NPP_WriteReady(NPP instance, NPStream* stream);
65int32_t NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer);
66void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname);
67void NPP_Print(NPP instance, NPPrint* platformPrint);
68int16_t NPP_HandleEvent(NPP instance, void* event);
69void NPP_URLNotify(NPP instance, const char* URL, NPReason reason, void* notifyData);
70NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value);
71NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value);
72
73#pragma export on
74// Mach-o entry points
75NPError NP_Initialize(NPNetscapeFuncs *browserFuncs);
76NPError NP_GetEntryPoints(NPPluginFuncs *pluginFuncs);
77void NP_Shutdown(void);
78#pragma export off
79
80NPError NP_Initialize(NPNetscapeFuncs* browserFuncs)
81{
82    browser = browserFuncs;
83    return NPERR_NO_ERROR;
84}
85
86NPError NP_GetEntryPoints(NPPluginFuncs* pluginFuncs)
87{
88    pluginFuncs->version = 11;
89    pluginFuncs->size = sizeof(pluginFuncs);
90    pluginFuncs->newp = NPP_New;
91    pluginFuncs->destroy = NPP_Destroy;
92    pluginFuncs->setwindow = NPP_SetWindow;
93    pluginFuncs->newstream = NPP_NewStream;
94    pluginFuncs->destroystream = NPP_DestroyStream;
95    pluginFuncs->asfile = NPP_StreamAsFile;
96    pluginFuncs->writeready = NPP_WriteReady;
97    pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write;
98    pluginFuncs->print = NPP_Print;
99    pluginFuncs->event = NPP_HandleEvent;
100    pluginFuncs->urlnotify = NPP_URLNotify;
101    pluginFuncs->getvalue = NPP_GetValue;
102    pluginFuncs->setvalue = NPP_SetValue;
103
104    return NPERR_NO_ERROR;
105}
106
107void NP_Shutdown(void)
108{
109
110}
111
112NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved)
113{
114    // Create per-instance storage
115    PluginObject *obj = (PluginObject *)malloc(sizeof(PluginObject));
116    bzero(obj, sizeof(PluginObject));
117
118    obj->npp = instance;
119    instance->pdata = obj;
120
121    // Ask the browser if it supports the CoreGraphics drawing model
122    NPBool supportsCoreGraphics;
123    if (browser->getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) != NPERR_NO_ERROR)
124        supportsCoreGraphics = FALSE;
125
126    if (!supportsCoreGraphics)
127        return NPERR_INCOMPATIBLE_VERSION_ERROR;
128
129    // If the browser supports the CoreGraphics drawing model, enable it.
130    browser->setvalue(instance, NPPVpluginDrawingModel, (void *)NPDrawingModelCoreGraphics);
131
132    // If the browser supports the Cocoa event model, enable it.
133    NPBool supportsCocoa;
134    if (browser->getvalue(instance, NPNVsupportsCocoaBool, &supportsCocoa) != NPERR_NO_ERROR)
135        supportsCocoa = FALSE;
136
137    if (!supportsCocoa)
138        return NPERR_INCOMPATIBLE_VERSION_ERROR;
139
140    browser->setvalue(instance, NPPVpluginEventModel, (void *)NPEventModelCocoa);
141
142    return NPERR_NO_ERROR;
143}
144
145NPError NPP_Destroy(NPP instance, NPSavedData** save)
146{
147    // Free per-instance storage
148    PluginObject *obj = instance->pdata;
149
150    [obj->string release];
151    [obj->menuHandler release];
152
153    free(obj);
154
155    return NPERR_NO_ERROR;
156}
157
158NPError NPP_SetWindow(NPP instance, NPWindow* window)
159{
160    PluginObject *obj = instance->pdata;
161    obj->window = *window;
162
163    return NPERR_NO_ERROR;
164}
165
166
167NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype)
168{
169    *stype = NP_ASFILEONLY;
170    return NPERR_NO_ERROR;
171}
172
173NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason)
174{
175    return NPERR_NO_ERROR;
176}
177
178int32_t NPP_WriteReady(NPP instance, NPStream* stream)
179{
180    return 0;
181}
182
183int32_t NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer)
184{
185    return 0;
186}
187
188void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
189{
190}
191
192void NPP_Print(NPP instance, NPPrint* platformPrint)
193{
194
195}
196
197static void handleDraw(PluginObject *obj, NPCocoaEvent *event)
198{
199    NSGraphicsContext *oldContext = [[NSGraphicsContext currentContext] retain];
200
201    NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithGraphicsPort:event->data.draw.context
202                                                                            flipped:YES];
203
204    [NSGraphicsContext setCurrentContext:context];
205
206    NSRect rect = NSMakeRect(0, 0, obj->window.width, obj->window.height);
207
208    [[NSColor lightGrayColor] set];
209    [NSBezierPath fillRect:rect];
210
211    // If the plugin has focus, draw a focus indicator
212    if (obj->hasFocus) {
213        [[NSColor blackColor] set];
214        NSBezierPath *path = [NSBezierPath bezierPathWithRect:rect];
215        [path setLineWidth:5];
216        [path stroke];
217    }
218
219    [obj->string drawAtPoint:NSMakePoint(10, 10) withAttributes:nil];
220
221    [NSGraphicsContext setCurrentContext:oldContext];
222}
223
224static NSString *eventType(NPCocoaEventType type)
225{
226    switch (type) {
227        case NPCocoaEventScrollWheel:
228            return @"NPCocoaEventScrollWheel";
229        case NPCocoaEventMouseDown:
230            return @"NPCocoaEventMouseDown";
231        case NPCocoaEventMouseUp:
232            return @"NPCocoaEventMouseUp";
233        case NPCocoaEventMouseMoved:
234            return @"NPCocoaEventMouseMoved";
235        case NPCocoaEventMouseDragged:
236            return @"NPCocoaEventMouseDragged";
237        case NPCocoaEventMouseEntered:
238            return @"NPCocoaEventMouseEntered";
239        case NPCocoaEventMouseExited:
240            return @"NPCocoaEventMouseExited";
241        case NPCocoaEventKeyDown:
242            return @"NPCocoaEventKeyDown";
243        case NPCocoaEventKeyUp:
244            return @"NPCocoaEventKeyUp";
245        case NPCocoaEventFlagsChanged:
246            return @"NPCocoaEventFlagsChanged";
247        default:
248            return @"unknown";
249    }
250}
251
252static void invalidatePlugin(PluginObject *obj)
253{
254    NPRect rect;
255    rect.left = 0;
256    rect.top = 0;
257    rect.right = obj->window.width;
258    rect.bottom = obj->window.height;
259
260    browser->invalidaterect(obj->npp, &rect);
261}
262
263
264static void handleMouseEvent(PluginObject *obj, NPCocoaEvent *event)
265{
266    NSString *string = [NSString stringWithFormat:@"Type: %@\n"
267                                                   "Modifier flags: 0x%x\n"
268                                                   "Coordinates: (%g, %g)\n"
269                                                   "Button number: %d\n"
270                                                   "Click count: %d\n"
271                                                   "Delta: (%g, %g, %g)",
272                                                   eventType(event->type),
273                                                   event->data.mouse.modifierFlags,
274                                                   event->data.mouse.pluginX,
275                                                   event->data.mouse.pluginY,
276                                                   event->data.mouse.buttonNumber,
277                                                   event->data.mouse.clickCount,
278                                                   event->data.mouse.deltaX, event->data.mouse.deltaY, event->data.mouse.deltaZ];
279
280
281    [obj->string release];
282    obj->string = [string retain];
283
284    invalidatePlugin(obj);
285
286    if (event->data.mouse.buttonNumber == 1) {
287        if (!obj->menuHandler)
288            obj->menuHandler = [[MenuHandler alloc] initWithBrowserFuncs:browser instance:obj->npp];
289
290        browser->popupcontextmenu(obj->npp, (NPNSMenu *)[obj->menuHandler menu]);
291    }
292}
293
294static void handleKeyboardEvent(PluginObject *obj, NPCocoaEvent *event)
295{
296    NSString *string = [NSString stringWithFormat:@"Type: %@\n"
297                        "Modifier flags: 0x%x\n"
298                        "Characters: %@\n"
299                        "Characters ignoring modifiers: %@\n"
300                        "Is a repeat: %@\n"
301                        "Key code: %d",
302                        eventType(event->type),
303                        event->data.key.modifierFlags,
304                        event->data.key.characters,
305                        event->data.key.charactersIgnoringModifiers,
306                        event->data.key.isARepeat ? @"YES" : @"NO",
307                        event->data.key.keyCode];
308
309
310    [obj->string release];
311    obj->string = [string retain];
312
313    invalidatePlugin(obj);
314}
315
316int16_t NPP_HandleEvent(NPP instance, void* event)
317{
318    PluginObject *obj = instance->pdata;
319
320    NPCocoaEvent *cocoaEvent = event;
321
322    switch(cocoaEvent->type) {
323        case NPCocoaEventFocusChanged:
324            obj->hasFocus = cocoaEvent->data.focus.hasFocus;
325            invalidatePlugin(obj);
326            return 1;
327
328        case NPCocoaEventDrawRect:
329            handleDraw(obj, cocoaEvent);
330            return 1;
331
332        case NPCocoaEventKeyDown:
333        case NPCocoaEventKeyUp:
334        case NPCocoaEventFlagsChanged:
335            handleKeyboardEvent(obj, cocoaEvent);
336            return 1;
337
338        case NPCocoaEventMouseDown:
339        case NPCocoaEventMouseUp:
340
341        // FIXME: NPCocoaEventMouseMoved is currently disabled in order to see other events more clearly
342        // without "drowning" in mouse moved events.
343//        case NPCocoaEventMouseMoved:
344        case NPCocoaEventMouseEntered:
345        case NPCocoaEventMouseExited:
346        case NPCocoaEventMouseDragged:
347        case NPCocoaEventScrollWheel:
348            handleMouseEvent(obj, cocoaEvent);
349            return 1;
350    }
351
352    return 0;
353}
354
355void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
356{
357
358}
359
360NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
361{
362    return NPERR_GENERIC_ERROR;
363}
364
365NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value)
366{
367    return NPERR_GENERIC_ERROR;
368}
369