Home | History | Annotate | Download | only in Plugins
      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