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/Vector.h> 33 34WebNetscapePluginEventHandlerCocoa::WebNetscapePluginEventHandlerCocoa(WebNetscapePluginView* pluginView) 35 : WebNetscapePluginEventHandler(pluginView) 36#ifndef __LP64__ 37 , m_keyEventHandler(0) 38#endif 39{ 40} 41 42static inline void initializeEvent(NPCocoaEvent* event, NPCocoaEventType type) 43{ 44 event->type = type; 45 event->version = 0; 46} 47 48void WebNetscapePluginEventHandlerCocoa::drawRect(CGContextRef context, const NSRect& rect) 49{ 50 NPCocoaEvent event; 51 52 initializeEvent(&event, NPCocoaEventDrawRect); 53 event.data.draw.context = context; 54 event.data.draw.x = rect.origin.x; 55 event.data.draw.y = rect.origin.y; 56 event.data.draw.width = rect.size.width; 57 event.data.draw.height = rect.size.height; 58 59 RetainPtr<CGContextRef> protect(context); 60 61 sendEvent(&event); 62} 63 64void WebNetscapePluginEventHandlerCocoa::mouseDown(NSEvent *event) 65{ 66 sendMouseEvent(event, NPCocoaEventMouseDown); 67} 68 69void WebNetscapePluginEventHandlerCocoa::mouseDragged(NSEvent *event) 70{ 71 sendMouseEvent(event, NPCocoaEventMouseDragged); 72} 73 74void WebNetscapePluginEventHandlerCocoa::mouseEntered(NSEvent *event) 75{ 76 sendMouseEvent(event, NPCocoaEventMouseEntered); 77} 78 79void WebNetscapePluginEventHandlerCocoa::mouseExited(NSEvent *event) 80{ 81 sendMouseEvent(event, NPCocoaEventMouseExited); 82} 83 84void WebNetscapePluginEventHandlerCocoa::mouseMoved(NSEvent *event) 85{ 86 sendMouseEvent(event, NPCocoaEventMouseMoved); 87} 88 89void WebNetscapePluginEventHandlerCocoa::mouseUp(NSEvent *event) 90{ 91 sendMouseEvent(event, NPCocoaEventMouseUp); 92} 93 94bool WebNetscapePluginEventHandlerCocoa::scrollWheel(NSEvent* event) 95{ 96 return sendMouseEvent(event, NPCocoaEventScrollWheel); 97} 98 99bool WebNetscapePluginEventHandlerCocoa::sendMouseEvent(NSEvent *nsEvent, NPCocoaEventType type) 100{ 101 NPCocoaEvent event; 102 103 NSPoint point = [m_pluginView convertPoint:[nsEvent locationInWindow] fromView:nil]; 104 105 int clickCount; 106 if (type == NPCocoaEventMouseEntered || type == NPCocoaEventMouseExited || type == NPCocoaEventScrollWheel) 107 clickCount = 0; 108 else 109 clickCount = [nsEvent clickCount]; 110 111 initializeEvent(&event, type); 112 event.data.mouse.modifierFlags = [nsEvent modifierFlags]; 113 event.data.mouse.buttonNumber = [nsEvent buttonNumber]; 114 event.data.mouse.clickCount = clickCount; 115 event.data.mouse.pluginX = point.x; 116 event.data.mouse.pluginY = point.y; 117 event.data.mouse.deltaX = [nsEvent deltaX]; 118 event.data.mouse.deltaY = [nsEvent deltaY]; 119 event.data.mouse.deltaZ = [nsEvent deltaZ]; 120 121 return sendEvent(&event); 122} 123 124void WebNetscapePluginEventHandlerCocoa::keyDown(NSEvent *event) 125{ 126 bool retval = sendKeyEvent(event, NPCocoaEventKeyDown); 127 128#ifndef __LP64__ 129 // If the plug-in did not handle the event, pass it on to the Input Manager. 130 if (retval) 131 WKSendKeyEventToTSM(event); 132#else 133 UNUSED_PARAM(retval); 134#endif 135} 136 137void WebNetscapePluginEventHandlerCocoa::keyUp(NSEvent *event) 138{ 139 sendKeyEvent(event, NPCocoaEventKeyUp); 140} 141 142void WebNetscapePluginEventHandlerCocoa::flagsChanged(NSEvent *nsEvent) 143{ 144 NPCocoaEvent event; 145 146 initializeEvent(&event, NPCocoaEventFlagsChanged); 147 event.data.key.modifierFlags = [nsEvent modifierFlags]; 148 event.data.key.keyCode = [nsEvent keyCode]; 149 event.data.key.isARepeat = false; 150 event.data.key.characters = 0; 151 event.data.key.charactersIgnoringModifiers = 0; 152 153 sendEvent(&event); 154} 155 156void WebNetscapePluginEventHandlerCocoa::syntheticKeyDownWithCommandModifier(int keyCode, char character) 157{ 158 char nullTerminatedString[] = { character, '\0' }; 159 160 RetainPtr<NSString> characters = adoptNS([[NSString alloc] initWithUTF8String:nullTerminatedString]); 161 162 NPCocoaEvent event; 163 initializeEvent(&event, NPCocoaEventKeyDown); 164 event.data.key.modifierFlags = NSCommandKeyMask; 165 event.data.key.keyCode = keyCode; 166 event.data.key.isARepeat = false; 167 event.data.key.characters = (NPNSString *)characters.get(); 168 event.data.key.charactersIgnoringModifiers = (NPNSString *)characters.get(); 169 170 sendEvent(&event); 171} 172 173bool WebNetscapePluginEventHandlerCocoa::sendKeyEvent(NSEvent* nsEvent, NPCocoaEventType type) 174{ 175 NPCocoaEvent event; 176 177 initializeEvent(&event, type); 178 event.data.key.modifierFlags = [nsEvent modifierFlags]; 179 event.data.key.keyCode = [nsEvent keyCode]; 180 event.data.key.isARepeat = [nsEvent isARepeat]; 181 event.data.key.characters = (NPNSString *)[nsEvent characters]; 182 event.data.key.charactersIgnoringModifiers = (NPNSString *)[nsEvent charactersIgnoringModifiers]; 183 184 return sendEvent(&event); 185} 186 187void WebNetscapePluginEventHandlerCocoa::windowFocusChanged(bool hasFocus) 188{ 189 NPCocoaEvent event; 190 191 initializeEvent(&event, NPCocoaEventWindowFocusChanged); 192 event.data.focus.hasFocus = hasFocus; 193 194 sendEvent(&event); 195} 196 197void WebNetscapePluginEventHandlerCocoa::focusChanged(bool hasFocus) 198{ 199 NPCocoaEvent event; 200 201 initializeEvent(&event, NPCocoaEventFocusChanged); 202 event.data.focus.hasFocus = hasFocus; 203 204 sendEvent(&event); 205 206 if (hasFocus) 207 installKeyEventHandler(); 208 else 209 removeKeyEventHandler(); 210} 211 212void* WebNetscapePluginEventHandlerCocoa::platformWindow(NSWindow* window) 213{ 214 return window; 215} 216 217bool WebNetscapePluginEventHandlerCocoa::sendEvent(NPCocoaEvent* event) 218{ 219 switch (event->type) { 220 case NPCocoaEventMouseDown: 221 case NPCocoaEventMouseUp: 222 case NPCocoaEventMouseDragged: 223 case NPCocoaEventKeyDown: 224 case NPCocoaEventKeyUp: 225 case NPCocoaEventFlagsChanged: 226 case NPCocoaEventScrollWheel: 227 m_currentEventIsUserGesture = true; 228 break; 229 default: 230 m_currentEventIsUserGesture = false; 231 } 232 233 bool result = [m_pluginView sendEvent:event isDrawRect:event->type == NPCocoaEventDrawRect]; 234 235 m_currentEventIsUserGesture = false; 236 return result; 237} 238 239#ifndef __LP64__ 240 241void WebNetscapePluginEventHandlerCocoa::installKeyEventHandler() 242{ 243 static const EventTypeSpec TSMEvents[] = 244 { 245 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } 246 }; 247 248 if (!m_keyEventHandler) 249 InstallEventHandler(GetWindowEventTarget((WindowRef)[[m_pluginView window] windowRef]), 250 NewEventHandlerUPP(TSMEventHandler), 251 GetEventTypeCount(TSMEvents), 252 TSMEvents, 253 this, 254 &m_keyEventHandler); 255} 256 257void WebNetscapePluginEventHandlerCocoa::removeKeyEventHandler() 258{ 259 if (m_keyEventHandler) { 260 RemoveEventHandler(m_keyEventHandler); 261 m_keyEventHandler = 0; 262 } 263} 264 265OSStatus WebNetscapePluginEventHandlerCocoa::TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef event, void* eventHandler) 266{ 267 return static_cast<WebNetscapePluginEventHandlerCocoa*>(eventHandler)->handleTSMEvent(event); 268} 269 270OSStatus WebNetscapePluginEventHandlerCocoa::handleTSMEvent(EventRef eventRef) 271{ 272 ASSERT(GetEventKind(eventRef) == kEventTextInputUnicodeForKeyEvent); 273 274 // Get the text buffer size. 275 ByteCount size; 276 OSStatus result = GetEventParameter(eventRef, kEventParamTextInputSendText, typeUnicodeText, 0, 0, &size, 0); 277 if (result != noErr) 278 return result; 279 280 unsigned length = size / sizeof(UniChar); 281 Vector<UniChar, 16> characters(length); 282 283 // Now get the actual text. 284 result = GetEventParameter(eventRef, kEventParamTextInputSendText, typeUnicodeText, 0, size, 0, characters.data()); 285 if (result != noErr) 286 return result; 287 288 RetainPtr<CFStringRef> text = adoptCF(CFStringCreateWithCharacters(0, characters.data(), length)); 289 290 NPCocoaEvent event; 291 292 initializeEvent(&event, NPCocoaEventTextInput); 293 event.data.text.text = (NPNSString*)text.get(); 294 295 sendEvent(&event); 296 297 return noErr; 298} 299 300#endif // __LP64__ 301 302#endif // ENABLE(NETSCAPE_PLUGIN_API) 303