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) 304