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 35WebNetscapePluginEventHandlerCocoa::WebNetscapePluginEventHandlerCocoa(WebNetscapePluginView* pluginView) 36 : WebNetscapePluginEventHandler(pluginView) 37#ifndef __LP64__ 38 , m_keyEventHandler(0) 39#endif 40{ 41} 42 43static inline void initializeEvent(NPCocoaEvent* event, NPCocoaEventType type) 44{ 45 event->type = type; 46 event->version = 0; 47} 48 49void 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 65void WebNetscapePluginEventHandlerCocoa::mouseDown(NSEvent *event) 66{ 67 sendMouseEvent(event, NPCocoaEventMouseDown); 68} 69 70void WebNetscapePluginEventHandlerCocoa::mouseDragged(NSEvent *event) 71{ 72 sendMouseEvent(event, NPCocoaEventMouseDragged); 73} 74 75void WebNetscapePluginEventHandlerCocoa::mouseEntered(NSEvent *event) 76{ 77 sendMouseEvent(event, NPCocoaEventMouseEntered); 78} 79 80void WebNetscapePluginEventHandlerCocoa::mouseExited(NSEvent *event) 81{ 82 sendMouseEvent(event, NPCocoaEventMouseExited); 83} 84 85void WebNetscapePluginEventHandlerCocoa::mouseMoved(NSEvent *event) 86{ 87 sendMouseEvent(event, NPCocoaEventMouseMoved); 88} 89 90void WebNetscapePluginEventHandlerCocoa::mouseUp(NSEvent *event) 91{ 92 sendMouseEvent(event, NPCocoaEventMouseUp); 93} 94 95bool WebNetscapePluginEventHandlerCocoa::scrollWheel(NSEvent* event) 96{ 97 return sendMouseEvent(event, NPCocoaEventScrollWheel); 98} 99 100bool 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 125void 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 138void WebNetscapePluginEventHandlerCocoa::keyUp(NSEvent *event) 139{ 140 sendKeyEvent(event, NPCocoaEventKeyUp); 141} 142 143void 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 157void 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 174bool 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 188void 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 198void 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 213void* WebNetscapePluginEventHandlerCocoa::platformWindow(NSWindow* window) 214{ 215 return window; 216} 217 218bool 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 242void 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 258void WebNetscapePluginEventHandlerCocoa::removeKeyEventHandler() 259{ 260 if (m_keyEventHandler) { 261 RemoveEventHandler(m_keyEventHandler); 262 m_keyEventHandler = 0; 263 } 264} 265 266OSStatus WebNetscapePluginEventHandlerCocoa::TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef event, void* eventHandler) 267{ 268 return static_cast<WebNetscapePluginEventHandlerCocoa*>(eventHandler)->handleTSMEvent(event); 269} 270 271OSStatus 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) 304