initial import
[vuplus_webkit] / Source / WebKit / mac / Plugins / WebNetscapePluginEventHandlerCocoa.mm
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #if ENABLE(NETSCAPE_PLUGIN_API)
27
28 #import "WebNetscapePluginEventHandlerCocoa.h"
29
30 #import "WebKitSystemInterface.h"
31 #import "WebNetscapePluginView.h"
32 #import <wtf/UnusedParam.h>
33 #import <wtf/Vector.h>
34
35 WebNetscapePluginEventHandlerCocoa::WebNetscapePluginEventHandlerCocoa(WebNetscapePluginView* pluginView)
36     : WebNetscapePluginEventHandler(pluginView)
37 #ifndef __LP64__
38     , m_keyEventHandler(0)
39 #endif
40 {
41 }
42
43 static inline void initializeEvent(NPCocoaEvent* event, NPCocoaEventType type)
44 {
45     event->type = type;
46     event->version = 0;
47 }
48
49 void WebNetscapePluginEventHandlerCocoa::drawRect(CGContextRef context, const NSRect& rect)
50 {
51     NPCocoaEvent event;
52     
53     initializeEvent(&event, NPCocoaEventDrawRect);
54     event.data.draw.context = context;
55     event.data.draw.x = rect.origin.x;
56     event.data.draw.y = rect.origin.y;
57     event.data.draw.width = rect.size.width;
58     event.data.draw.height = rect.size.height;
59     
60     RetainPtr<CGContextRef> protect(context);
61     
62     sendEvent(&event);
63 }
64
65 void WebNetscapePluginEventHandlerCocoa::mouseDown(NSEvent *event)
66 {
67     sendMouseEvent(event, NPCocoaEventMouseDown);
68 }
69
70 void WebNetscapePluginEventHandlerCocoa::mouseDragged(NSEvent *event)
71 {
72     sendMouseEvent(event, NPCocoaEventMouseDragged);
73 }
74
75 void WebNetscapePluginEventHandlerCocoa::mouseEntered(NSEvent *event)
76 {
77     sendMouseEvent(event, NPCocoaEventMouseEntered);
78 }
79
80 void WebNetscapePluginEventHandlerCocoa::mouseExited(NSEvent *event)
81 {
82     sendMouseEvent(event, NPCocoaEventMouseExited);
83 }
84
85 void WebNetscapePluginEventHandlerCocoa::mouseMoved(NSEvent *event)
86 {
87     sendMouseEvent(event, NPCocoaEventMouseMoved);
88 }
89
90 void WebNetscapePluginEventHandlerCocoa::mouseUp(NSEvent *event)
91 {
92     sendMouseEvent(event, NPCocoaEventMouseUp);
93 }
94
95 bool WebNetscapePluginEventHandlerCocoa::scrollWheel(NSEvent* event)
96 {
97     return sendMouseEvent(event, NPCocoaEventScrollWheel);
98 }
99
100 bool WebNetscapePluginEventHandlerCocoa::sendMouseEvent(NSEvent *nsEvent, NPCocoaEventType type)
101 {
102     NPCocoaEvent event;
103     
104     NSPoint point = [m_pluginView convertPoint:[nsEvent locationInWindow] fromView:nil];
105     
106     int clickCount;
107     if (type == NPCocoaEventMouseEntered || type == NPCocoaEventMouseExited || type == NPCocoaEventScrollWheel)
108         clickCount = 0;
109     else
110         clickCount = [nsEvent clickCount];
111     
112     initializeEvent(&event, type);
113     event.data.mouse.modifierFlags = [nsEvent modifierFlags];
114     event.data.mouse.buttonNumber = [nsEvent buttonNumber];
115     event.data.mouse.clickCount = clickCount;
116     event.data.mouse.pluginX = point.x;
117     event.data.mouse.pluginY = point.y;
118     event.data.mouse.deltaX = [nsEvent deltaX];
119     event.data.mouse.deltaY = [nsEvent deltaY];
120     event.data.mouse.deltaZ = [nsEvent deltaZ];
121     
122     return sendEvent(&event);
123 }
124
125 void WebNetscapePluginEventHandlerCocoa::keyDown(NSEvent *event)
126 {
127     bool retval = sendKeyEvent(event, NPCocoaEventKeyDown);
128     
129 #ifndef __LP64__
130     // If the plug-in did not handle the event, pass it on to the Input Manager.
131     if (retval)
132         WKSendKeyEventToTSM(event);
133 #else
134     UNUSED_PARAM(retval);
135 #endif
136 }
137
138 void WebNetscapePluginEventHandlerCocoa::keyUp(NSEvent *event)
139 {
140     sendKeyEvent(event, NPCocoaEventKeyUp);
141 }
142
143 void WebNetscapePluginEventHandlerCocoa::flagsChanged(NSEvent *nsEvent)
144 {
145     NPCocoaEvent event;
146         
147     initializeEvent(&event, NPCocoaEventFlagsChanged);
148     event.data.key.modifierFlags = [nsEvent modifierFlags];
149     event.data.key.keyCode = [nsEvent keyCode];
150     event.data.key.isARepeat = false;
151     event.data.key.characters = 0;
152     event.data.key.charactersIgnoringModifiers = 0;
153     
154     sendEvent(&event);
155 }
156
157 void WebNetscapePluginEventHandlerCocoa::syntheticKeyDownWithCommandModifier(int keyCode, char character)
158 {
159     char nullTerminatedString[] = { character, '\0' };
160     
161     RetainPtr<NSString> characters(AdoptNS, [[NSString alloc] initWithUTF8String:nullTerminatedString]);
162     
163     NPCocoaEvent event;
164     initializeEvent(&event, NPCocoaEventKeyDown);
165     event.data.key.modifierFlags = NSCommandKeyMask;
166     event.data.key.keyCode = keyCode;
167     event.data.key.isARepeat = false;
168     event.data.key.characters = (NPNSString *)characters.get();
169     event.data.key.charactersIgnoringModifiers = (NPNSString *)characters.get();
170
171     sendEvent(&event);
172 }
173
174 bool WebNetscapePluginEventHandlerCocoa::sendKeyEvent(NSEvent* nsEvent, NPCocoaEventType type)
175 {
176     NPCocoaEvent event;
177
178     initializeEvent(&event, type);
179     event.data.key.modifierFlags = [nsEvent modifierFlags];
180     event.data.key.keyCode = [nsEvent keyCode];
181     event.data.key.isARepeat = [nsEvent isARepeat];
182     event.data.key.characters = (NPNSString *)[nsEvent characters];
183     event.data.key.charactersIgnoringModifiers = (NPNSString *)[nsEvent charactersIgnoringModifiers];
184      
185     return sendEvent(&event);
186 }
187
188 void WebNetscapePluginEventHandlerCocoa::windowFocusChanged(bool hasFocus)
189 {
190     NPCocoaEvent event;
191     
192     initializeEvent(&event, NPCocoaEventWindowFocusChanged);
193     event.data.focus.hasFocus = hasFocus;
194     
195     sendEvent(&event);
196 }
197
198 void WebNetscapePluginEventHandlerCocoa::focusChanged(bool hasFocus)
199 {
200     NPCocoaEvent event;
201
202     initializeEvent(&event, NPCocoaEventFocusChanged);
203     event.data.focus.hasFocus = hasFocus;
204     
205     sendEvent(&event);
206     
207     if (hasFocus)
208         installKeyEventHandler();
209     else
210         removeKeyEventHandler();
211 }
212
213 void* WebNetscapePluginEventHandlerCocoa::platformWindow(NSWindow* window)
214 {
215     return window;
216 }
217
218 bool WebNetscapePluginEventHandlerCocoa::sendEvent(NPCocoaEvent* event)
219 {
220     switch (event->type) {
221         case NPCocoaEventMouseDown:
222         case NPCocoaEventMouseUp:
223         case NPCocoaEventMouseDragged:
224         case NPCocoaEventKeyDown:
225         case NPCocoaEventKeyUp:
226         case NPCocoaEventFlagsChanged:
227         case NPCocoaEventScrollWheel:
228             m_currentEventIsUserGesture = true;
229             break;
230         default:
231             m_currentEventIsUserGesture = false;
232     }
233             
234     bool result = [m_pluginView sendEvent:event isDrawRect:event->type == NPCocoaEventDrawRect];
235     
236     m_currentEventIsUserGesture = false;
237     return result;
238 }
239
240 #ifndef __LP64__
241
242 void WebNetscapePluginEventHandlerCocoa::installKeyEventHandler()
243 {
244     static const EventTypeSpec TSMEvents[] =
245     {
246         { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }
247     };
248     
249     if (!m_keyEventHandler)
250         InstallEventHandler(GetWindowEventTarget((WindowRef)[[m_pluginView window] windowRef]),
251                             NewEventHandlerUPP(TSMEventHandler),
252                             GetEventTypeCount(TSMEvents),
253                             TSMEvents,
254                             this,
255                             &m_keyEventHandler);
256 }
257
258 void WebNetscapePluginEventHandlerCocoa::removeKeyEventHandler()
259 {
260     if (m_keyEventHandler) {
261         RemoveEventHandler(m_keyEventHandler);
262         m_keyEventHandler = 0;
263     }    
264 }
265
266 OSStatus WebNetscapePluginEventHandlerCocoa::TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef event, void* eventHandler)
267 {
268     return static_cast<WebNetscapePluginEventHandlerCocoa*>(eventHandler)->handleTSMEvent(event);
269 }
270
271 OSStatus WebNetscapePluginEventHandlerCocoa::handleTSMEvent(EventRef eventRef)
272 {
273     ASSERT(GetEventKind(eventRef) == kEventTextInputUnicodeForKeyEvent);
274     
275     // Get the text buffer size.
276     ByteCount size;
277     OSStatus result = GetEventParameter(eventRef, kEventParamTextInputSendText, typeUnicodeText, 0, 0, &size, 0);
278     if (result != noErr)
279         return result;
280     
281     unsigned length = size / sizeof(UniChar);
282     Vector<UniChar, 16> characters(length);
283     
284     // Now get the actual text.
285     result = GetEventParameter(eventRef, kEventParamTextInputSendText, typeUnicodeText, 0, size, 0, characters.data());
286     if (result != noErr)
287         return result;
288
289     RetainPtr<CFStringRef> text(AdoptCF, CFStringCreateWithCharacters(0, characters.data(), length));
290
291     NPCocoaEvent event;
292     
293     initializeEvent(&event, NPCocoaEventTextInput);
294     event.data.text.text = (NPNSString*)text.get();
295     
296     sendEvent(&event);
297
298     return noErr;
299 }
300
301 #endif // __LP64__
302
303 #endif // ENABLE(NETSCAPE_PLUGIN_API)