Changeset 136124 in webkit


Ignore:
Timestamp:
Nov 29, 2012 5:25:53 AM (11 years ago)
Author:
Simon Hausmann
Message:

[Qt] Implement support for Cocoa based NPAPI plugins on Mac
https://bugs.webkit.org/show_bug.cgi?id=72358

Patch by Andy Shaw <andy.shaw@digia.com> on 2012-11-29
Reviewed by Simon Hausmann.

With later versions of Flash they are only Cocoa based which meant that it was not possible to use Flash in a QtWebKit browser.
This makes it possible to also use 64bit based plugins too.

  • plugins/PluginPackage.cpp:

(WebCore::PluginPackage::initializeBrowserFuncs):
(WebCore):

  • plugins/PluginQuirkSet.h:
  • plugins/PluginView.cpp:

(WebCore::PluginView::handleEvent):
(WebCore::PluginView::PluginView):
(WebCore):
(WebCore::PluginView::userAgent):

  • plugins/PluginView.h:

(WebCore):
(PluginView):

  • plugins/mac/PluginPackageMac.cpp:

(WebCore::PluginPackage::determineQuirks):
(WebCore::PluginPackage::fetchInfo):

  • plugins/mac/PluginViewMac.mm:

(WebCore):
(WebCore::initializeNPCocoaEvent):
(WebCore::getModifiers):
(WebCore::PluginView::platformStart):

  • plugins/npapi.cpp:

(NPN_PopUpContextMenu):

  • plugins/npapi.h:
Location:
trunk/Source/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r136113 r136124  
     12012-11-29  Andy Shaw  <andy.shaw@digia.com>
     2
     3        [Qt] Implement support for Cocoa based NPAPI plugins on Mac
     4        https://bugs.webkit.org/show_bug.cgi?id=72358
     5
     6        Reviewed by Simon Hausmann.
     7
     8        With later versions of Flash they are only Cocoa based which meant that it was not possible to use Flash in a QtWebKit browser.
     9        This makes it possible to also use 64bit based plugins too. 
     10
     11        * plugins/PluginPackage.cpp:
     12        (WebCore::PluginPackage::initializeBrowserFuncs):
     13        (WebCore):
     14        * plugins/PluginQuirkSet.h:
     15        * plugins/PluginView.cpp:
     16        (WebCore::PluginView::handleEvent):
     17        (WebCore::PluginView::PluginView):
     18        (WebCore):
     19        (WebCore::PluginView::userAgent):
     20        * plugins/PluginView.h:
     21        (WebCore):
     22        (PluginView):
     23        * plugins/mac/PluginPackageMac.cpp:
     24        (WebCore::PluginPackage::determineQuirks):
     25        (WebCore::PluginPackage::fetchInfo):
     26        * plugins/mac/PluginViewMac.mm:
     27        (WebCore):
     28        (WebCore::initializeNPCocoaEvent):
     29        (WebCore::getModifiers):
     30        (WebCore::PluginView::platformStart):
     31        * plugins/npapi.cpp:
     32        (NPN_PopUpContextMenu):
     33        * plugins/npapi.h:
     34
    1352012-11-29  Sheriff Bot  <webkit.review.bot@gmail.com>
    236
  • trunk/Source/WebCore/plugins/PluginPackage.cpp

    r134222 r136124  
    331331    m_browserFuncs.setvalueforurl = NPN_SetValueForURL;
    332332    m_browserFuncs.getauthenticationinfo = NPN_GetAuthenticationInfo;
    333 }
    334 #endif
     333
     334    m_browserFuncs.popupcontextmenu = NPN_PopUpContextMenu;
     335}
     336#endif // ENABLE(NETSCAPE_PLUGIN_API)
    335337
    336338#if ENABLE(PLUGIN_PACKAGE_SIMPLE_HASH)
  • trunk/Source/WebCore/plugins/PluginQuirkSet.h

    r95901 r136124  
    4949        PluginQuirkRequiresDefaultScreenDepth = 1 << 13,
    5050        PluginQuirkDontCallSetWindowMoreThanOnce = 1 << 14,
    51         PluginQuirkIgnoreRightClickInWindowlessMode = 1 << 15
     51        PluginQuirkIgnoreRightClickInWindowlessMode = 1 << 15,
     52        PluginQuirkWantsChromeUserAgent = 1 << 16
    5253    };
    5354
  • trunk/Source/WebCore/plugins/PluginView.cpp

    r135952 r136124  
    6363#include "SecurityOrigin.h"
    6464#include "Settings.h"
     65#include "WheelEvent.h"
    6566#include "npruntime_impl.h"
    6667#include <wtf/ASCIICType.h>
     
    170171    else if (event->isKeyboardEvent())
    171172        handleKeyboardEvent(static_cast<KeyboardEvent*>(event));
     173#if defined(XP_MACOSX)
     174    else if (event->type() == eventNames().mousewheelEvent)
     175        handleWheelEvent(static_cast<WheelEvent*>(event));
     176#endif
    172177    else if (event->type() == eventNames().contextmenuEvent)
    173178        event->setDefaultHandled(); // We don't know if the plug-in has handled mousedown event by displaying a context menu, so we never want WebKit to show a default one.
     
    833838#if defined(XP_MACOSX)
    834839    , m_isWindowed(false)
     840    , m_updatedCocoaTextInputRequested(false)
     841    , m_keyDownSent(false)
     842    , m_disregardKeyUpCounter(0)
    835843#else
    836844    , m_isWindowed(true)
     
    12561264        " en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0";
    12571265
     1266static const char* const ChromeUserAgent = "Mozilla/5.0 ("
     1267#if defined(XP_MACOSX)
     1268    "Macintosh; U; Intel Mac OS X;"
     1269#elif defined(XP_WIN)
     1270    "Windows; U; Windows NT 5.1;"
     1271#elif defined(XP_UNIX)
     1272    // The Gtk port uses X11 plugins in Mac.
     1273#if OS(DARWIN) && PLATFORM(GTK)
     1274    "X11; U; Intel Mac OS X;"
     1275#else
     1276    "X11; U; Linux i686;"
     1277#endif
     1278#endif
     1279    " AppleWebKit/534.34 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/534.34";
     1280
    12581281const char* PluginView::userAgent()
    12591282{
    12601283    if (m_plugin->quirks().contains(PluginQuirkWantsMozillaUserAgent))
    12611284        return MozillaUserAgent;
    1262 
     1285    else if (m_plugin->quirks().contains(PluginQuirkWantsChromeUserAgent))
     1286        return ChromeUserAgent;
    12631287    if (m_userAgent.isNull())
    12641288        m_userAgent = m_parentFrame->loader()->userAgent(m_url).utf8();
  • trunk/Source/WebCore/plugins/PluginView.h

    r120956 r136124  
    9999    class ResourceError;
    100100    class ResourceResponse;
     101    class WheelEvent;
    101102
    102103    enum PluginStatus {
     
    230231        const KURL& url() const { return m_url; }
    231232
     233#if defined(XP_MACOSX) && ENABLE(NETSCAPE_PLUGIN_API)
     234        bool popUpContextMenu(NPMenu*);
     235#endif
     236
    232237#if OS(WINDOWS) && ENABLE(NETSCAPE_PLUGIN_API)
    233238        static LRESULT CALLBACK PluginViewWndProc(HWND, UINT, WPARAM, LPARAM);
     
    323328        bool dispatchNPEvent(NPEvent&);
    324329#endif // ENABLE(NETSCAPE_PLUGIN_API)
     330#endif
     331#if defined(XP_MACOSX) && ENABLE(NETSCAPE_PLUGIN_API)
     332        int16_t dispatchNPCocoaEvent(NPCocoaEvent&);
     333        bool m_updatedCocoaTextInputRequested;
     334        bool m_keyDownSent;
     335        bool m_usePixmap;
     336        uint16_t m_disregardKeyUpCounter;
     337#endif
     338
     339#if defined(XP_MACOSX)
     340        void handleWheelEvent(WheelEvent*);
    325341#endif
    326342        void updatePluginWidget();
  • trunk/Source/WebCore/plugins/mac/PluginPackageMac.cpp

    r115710 r136124  
    5858
    5959    if (mimeType == "application/x-shockwave-flash") {
    60         // The flash plugin only requests windowless plugins if we return a mozilla user agent
    61         m_quirks.add(PluginQuirkWantsMozillaUserAgent);
     60        m_quirks.add(PluginQuirkWantsChromeUserAgent);
    6261        m_quirks.add(PluginQuirkThrottleInvalidate);
    6362        m_quirks.add(PluginQuirkThrottleWMUserPlusOneMessages);
     
    197196            String description = (CFStringRef)CFDictionaryGetValue(extensionsDict.get(), CFSTR("WebPluginTypeDescription"));
    198197            m_mimeToDescriptions.set(mimeType, description);
     198            determineQuirks(mimeType);
    199199        }
    200200
  • trunk/Source/WebCore/plugins/mac/PluginViewMac.mm

    r127191 r136124  
    5959#include "ScriptController.h"
    6060#include "Settings.h"
     61#include "WheelEvent.h"
    6162#include "npruntime_impl.h"
    6263#include "runtime_root.h"
     
    7677#include <QKeyEvent>
    7778#include <QPainter>
     79#include <QDateTime>
     80#include <QPixmap>
    7881#include "QWebPageClient.h"
    7982QT_BEGIN_NAMESPACE
    8083extern Q_GUI_EXPORT OSWindowRef qt_mac_window_for(const QWidget* w);
     84extern Q_GUI_EXPORT CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); //qpaintdevice_mac.cpp
    8185QT_END_NAMESPACE
    8286#endif
     
    143147#endif
    144148    return IntPoint();
     149}
     150
     151// --------- Cocoa specific utility functions ----------
     152
     153static void initializeNPCocoaEvent(NPCocoaEvent* event)
     154{
     155    memset(event, 0, sizeof(NPCocoaEvent));
     156}
     157
     158static int32_t getModifiers(UIEventWithKeyState *event)
     159{
     160    int32_t modifiers = 0;
     161    if (event->keyCode() == 57) modifiers |= NSAlphaShiftKeyMask;
     162    if (event->shiftKey())  modifiers |= NSShiftKeyMask;
     163    if (event->ctrlKey())   modifiers |= NSControlKeyMask;
     164    if (event->metaKey())   modifiers |= NSCommandKeyMask;
     165    if (event->altKey())    modifiers |= NSAlternateKeyMask;
     166
     167    return modifiers;
    145168}
    146169
     
    180203    if (getValueStatic(NPNVariable(NPNVsupportsCarbonBool + m_eventModel), &eventModelSupported) != NPERR_NO_ERROR
    181204            || !eventModelSupported) {
     205#else
     206    NPBool eventModelSupported;
     207    if (getValueStatic(NPNVariable(NPNVsupportsCocoaBool/* + m_eventModel*/), &eventModelSupported) != NPERR_NO_ERROR
     208            || !eventModelSupported) {
    182209#endif
    183210        m_status = PluginStatusCanNotLoadPlugin;
     
    185212                m_plugin->name().utf8().data(), prettyNameForEventModel(m_eventModel));
    186213        return false;
    187 #ifndef NP_NO_CARBON
    188     }
    189 #endif
     214    }
    190215
    191216#ifndef NP_NO_QUICKDRAW
     
    193218    if (getValueStatic(NPNVariable(NPNVsupportsQuickDrawBool + m_drawingModel), &drawingModelSupported) != NPERR_NO_ERROR
    194219            || !drawingModelSupported) {
    195 #endif
    196220        m_status = PluginStatusCanNotLoadPlugin;
    197221        LOG(Plugins, "Plug-in '%s' uses unsupported drawing model %s",
    198222                m_plugin->name().utf8().data(), prettyNameForDrawingModel(m_drawingModel));
    199223        return false;
    200 #ifndef NP_NO_QUICKDRAW
    201     }
    202 #endif
     224    }
     225#endif
     226
     227#ifdef NP_NO_QUICKDRAW
     228    NPBool drawingModelSupported;
     229    if (getValueStatic(NPNVariable(NPNVsupportsCoreGraphicsBool/* + m_drawingModel*/), &drawingModelSupported) != NPERR_NO_ERROR
     230            || !drawingModelSupported) {
     231        m_status = PluginStatusCanNotLoadPlugin;
     232        LOG(Plugins, "Plug-in '%s' uses unsupported drawing model %s",
     233                m_plugin->name().utf8().data(), prettyNameForDrawingModel(m_drawingModel));
     234        return false;
     235    }
     236#endif
     237
    203238
    204239#if PLATFORM(QT)
     
    216251
    217252    // Create a fake window relative to which all events will be sent when using offscreen rendering
     253#ifndef NP_NO_CARBON
    218254    if (!platformPluginWidget()) {
    219 #ifndef NP_NO_CARBON
    220255        // Make the default size really big. It is unclear why this is required but with a smaller size, mouse move
    221256        // events don't get processed. Resizing the fake window to flash's size doesn't help.
     
    224259        // Flash requires the window to be hilited to process mouse move events.
    225260        HiliteWindow(m_fakeWindow, true);
    226 #endif
    227     }
     261    }
     262#endif
    228263
    229264    updatePluginWidget();
     
    232267        setNPWindowIfNeeded();
    233268
     269#ifndef NP_NO_CARBON
    234270    // TODO: Implement null timer throttling depending on plugin activation
    235271    m_nullEventTimer = adoptPtr(new Timer<PluginView>(this, &PluginView::nullEventTimerFired));
     
    237273
    238274    m_lastMousePos.h = m_lastMousePos.v = 0;
     275#endif // NP_NO_CARBON
    239276
    240277    return true;
     
    277314#endif
    278315    case NPNVsupportsCocoaBool:
    279         *static_cast<NPBool*>(value) = false;
     316        *static_cast<NPBool*>(value) = true;
    280317        *result = NPERR_NO_ERROR;
    281318        return true;
     
    287324        return true;
    288325
     326    case NPNVsupportsAdvancedKeyHandling:
     327        *static_cast<NPBool*>(value) = true;
     328        *result = NPERR_NO_ERROR;
     329        return true;
     330
    289331#ifndef NP_NO_QUICKDRAW
    290332    // QuickDraw is deprecated in 10.5 and not supported on 64-bit
     
    305347bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* error)
    306348{
     349    // In WebKit2, this is set if the plugin queries it's availiablity and
     350    // no key down events have already been sent.
     351    if (variable == NPNVsupportsUpdatedCocoaTextInputBool) {
     352        if (m_keyDownSent && !m_updatedCocoaTextInputRequested) {
     353            *static_cast<NPBool*>(value) = false;
     354            *error = NPERR_NO_ERROR;
     355        }
     356        else {
     357            *static_cast<NPBool*>(value) = true;
     358            *error = NPERR_NO_ERROR;
     359            m_updatedCocoaTextInputRequested = true;
     360        }
     361        return true;
     362    }
    307363    return false;
    308364}
     
    343399    if (!focused) {
    344400        Widget::setFocus(focused);
    345         return;
     401        if (m_eventModel != NPEventModelCocoa)
     402            return;
    346403    }
    347404
    348405    if (platformPluginWidget())
    349406#if PLATFORM(QT)
    350        static_cast<QWidget*>(platformPluginWidget())->setFocus(Qt::OtherFocusReason);
     407        static_cast<QWidget*>(platformPluginWidget())->setFocus(Qt::OtherFocusReason);
    351408#else
    352409        platformPluginWidget()->SetFocus();
    353410#endif
    354    else
    355        Widget::setFocus(focused);
    356 
     411    else
     412        Widget::setFocus(focused);
     413
     414
     415#ifndef NP_NO_CARBON
    357416    // TODO: Also handle and pass on blur events (focus lost)
    358 
    359 #ifndef NP_NO_CARBON
    360417    EventRecord record;
    361418    record.what = NPEventType_GetFocusEvent;
     
    368425        LOG(Events, "PluginView::setFocus(%d): Focus event not accepted", focused);
    369426#endif
     427    {
     428        NPCocoaEvent cocoaEvent;
     429        initializeNPCocoaEvent(&cocoaEvent);
     430        cocoaEvent.type = NPCocoaEventFocusChanged;
     431        NPBool focus = focused;
     432        cocoaEvent.data.focus.hasFocus = focus;
     433
     434        if(!dispatchNPCocoaEvent(cocoaEvent)) {
     435            LOG(Events, "PluginView::setFocus(): Focus event %d not accepted", cocoaEvent.type);
     436        }
     437    }
    370438}
    371439
     
    400468    }
    401469
    402     if (!newContextRef || !newWindowRef)
    403         return;
     470    if (!newContextRef || !newWindowRef) {
     471        if (!m_usePixmap)
     472            return;
     473    }
    404474
    405475    m_npWindow.window = (void*)&m_npCgContext;
     
    475545    if (context->paintingDisabled())
    476546        return;
    477 
     547#if PLATFORM(QT)
     548    QPainter* p = context->platformContext();
     549    CGContextRef cgContext = qt_mac_cg_context(p->device());
     550#else
     551    CGContextRef cgContext = m_npCgContext.context;
     552#endif
    478553    setNPWindowIfNeeded();
    479 
    480     CGContextRef cgContext = m_npCgContext.context;
    481     if (!cgContext)
    482         return;
     554    if (!cgContext) {
     555        cgContext = m_contextRef;
     556        if (!cgContext)
     557            return;
     558        else {
     559            m_usePixmap = true;
     560            setNPWindowIfNeeded();
     561        }
     562    } else
     563        m_usePixmap = false;
     564
     565    bool oldUsePixmap = m_usePixmap;
     566    if (m_isTransparent && !m_usePixmap) {
     567        if (m_pixmap.isNull())
     568            m_pixmap = QPixmap(frameRect().size());
     569        m_usePixmap = true;
     570        setNPWindowIfNeeded();
     571        cgContext = qt_mac_cg_context(&m_pixmap);
     572    }
    483573
    484574    CGContextSaveGState(cgContext);
     
    499589    CGContextClipToRect(cgContext, r);
    500590
    501     if (!platformPluginWidget() && m_isTransparent) { // clean the pixmap in transparent mode
     591    if (!platformPluginWidget() || m_isTransparent) { // clean the pixmap in transparent mode
    502592#if PLATFORM(QT)
    503593        QPainter painter(&m_pixmap);
     
    508598
    509599#ifndef NP_NO_CARBON
    510     EventRecord event;
    511     event.what = updateEvt;
    512     event.message = (long unsigned int)m_npCgContext.window;
    513     event.when = TickCount();
    514     event.where.h = 0;
    515     event.where.v = 0;
    516     event.modifiers = GetCurrentKeyModifiers();
    517 
    518     if (!dispatchNPEvent(event))
    519         LOG(Events, "PluginView::paint(): Paint event not accepted");
    520 #endif
    521 
    522     CGContextRestoreGState(cgContext);
    523 
    524     if (!platformPluginWidget()) {
     600    if (m_eventModel != NPEventModelCocoa) {
     601        EventRecord event;
     602        event.what = updateEvt;
     603        event.message = (long unsigned int)m_npCgContext.window;
     604        event.when = TickCount();
     605        event.where.h = 0;
     606        event.where.v = 0;
     607        event.modifiers = GetCurrentKeyModifiers();
     608
     609        if (!dispatchNPEvent(event))
     610            LOG(Events, "PluginView::paint(): Paint event not accepted");
     611    } else
     612#endif
     613    {
     614        NPCocoaEvent cocoaEvent;
     615        initializeNPCocoaEvent(&cocoaEvent);
     616        cocoaEvent.type = NPCocoaEventDrawRect;
     617        cocoaEvent.data.draw.x = m_usePixmap ? 0 : r.origin.x;
     618        cocoaEvent.data.draw.y = m_usePixmap ? 0 : r.origin.y;
     619        cocoaEvent.data.draw.width = m_usePixmap ? m_pixmap.width() : r.size.width;
     620        cocoaEvent.data.draw.height = m_usePixmap ? m_pixmap.height() : r.size.height;
     621        cocoaEvent.data.draw.context = cgContext;
     622       
     623        if(!dispatchNPCocoaEvent(cocoaEvent))
     624            LOG(Events, "PluginView::paint(): Paint event type %d not accepted", cocoaEvent.type);
     625    }
     626   
     627    if (!platformPluginWidget() || m_isTransparent) {
    525628#if PLATFORM(QT)
    526629        QPainter* painter = context->platformContext();
    527         painter->drawPixmap(targetRect.x(), targetRect.y(), m_pixmap, 
     630        painter->drawPixmap(targetRect.x(), targetRect.y(), m_pixmap,
    528631                            targetRect.x() - frameRect().x(), targetRect.y() - frameRect().y(), targetRect.width(), targetRect.height());
    529632#endif
    530633    }
    531 }
    532 
     634    CGContextRestoreGState(cgContext);
     635    if (oldUsePixmap != m_usePixmap) {
     636        m_usePixmap = oldUsePixmap;
     637        m_pixmap = QPixmap();
     638    }   
     639}
     640
     641bool PluginView::popUpContextMenu(NPMenu *menu)
     642{
     643    NSEvent* currentEvent = [NSApp currentEvent];
     644   
     645    // NPN_PopUpContextMenu must be called from within the plug-in's NPP_HandleEvent.
     646    if (!currentEvent)
     647        return NPERR_GENERIC_ERROR;
     648   
     649    NSWindow* window = [currentEvent window];
     650    NSView* view = [window contentView];
     651    [NSMenu popUpContextMenu:(NSMenu*)menu withEvent:currentEvent forView:view];
     652    return true;
     653}
     654   
    533655void PluginView::invalidateRect(const IntRect& rect)
    534656{
    535     if (platformPluginWidget())
     657    if (platformPluginWidget() && m_isTransparent)
    536658#if PLATFORM(QT)
    537659        static_cast<QWidget*>(platformPluginWidget())->update(convertToContainingWindow(rect));
     
    539661        platformPluginWidget()->RefreshRect(convertToContainingWindow(rect));
    540662#endif
    541     else
    542         invalidateWindowlessPluginRect(rect);
     663    invalidateWindowlessPluginRect(rect);
    543664}
    544665
     
    562683
    563684// ----------------- Event handling --------------------
     685void PluginView::handleWheelEvent(WheelEvent *event)
     686{
     687    if (!m_isStarted || m_eventModel != NPEventModelCocoa)
     688        return;
     689   
     690    NPCocoaEvent cocoaEvent;
     691    initializeNPCocoaEvent(&cocoaEvent);
     692   
     693    NSEvent *currentEvent = [NSApp currentEvent];
     694   
     695    cocoaEvent.type = NPCocoaEventScrollWheel;
     696   
     697    cocoaEvent.data.mouse.pluginX = event->layerX() - m_npWindow.x + m_windowRect.x() - m_element->offsetLeft();
     698    cocoaEvent.data.mouse.pluginY = event->layerY() - m_npWindow.y + m_windowRect.y() - m_element->offsetTop();
     699    cocoaEvent.data.mouse.deltaX = [currentEvent deltaX];
     700    cocoaEvent.data.mouse.deltaY = [currentEvent deltaY];
     701    cocoaEvent.data.mouse.deltaZ = [currentEvent deltaZ];
     702    cocoaEvent.data.mouse.modifierFlags = getModifiers(event);
     703   
     704    if(!dispatchNPCocoaEvent(cocoaEvent)) {
     705        LOG(Events, "PluginView::handleMouseEvent(): Wheel event type %d at %d,%d not accepted", cocoaEvent.type
     706            cocoaEvent.data.mouse.x, cocoaEvent.data.mouse.y);
     707    }
     708    event->setDefaultHandled();
     709}
    564710
    565711void PluginView::handleMouseEvent(MouseEvent* event)
     
    567713    if (!m_isStarted)
    568714        return;
    569 
    570 #ifndef NP_NO_CARBON
    571     EventRecord record;
    572 
    573     if (event->type() == eventNames().mousemoveEvent) {
    574         // Mouse movement is handled by null timer events
    575         m_lastMousePos = mousePosForPlugin(event);
    576         return;
    577     } else if (event->type() == eventNames().mouseoverEvent) {
    578         record.what = NPEventType_AdjustCursorEvent;
    579     } else if (event->type() == eventNames().mouseoutEvent) {
    580         record.what = NPEventType_AdjustCursorEvent;
    581     } else if (event->type() == eventNames().mousedownEvent) {
    582         record.what = mouseDown;
    583         // The plugin needs focus to receive keyboard events
    584         if (Page* page = m_parentFrame->page())
    585             page->focusController()->setFocusedFrame(m_parentFrame);
    586         m_parentFrame->document()->setFocusedNode(m_element);
    587     } else if (event->type() == eventNames().mouseupEvent) {
    588         record.what = mouseUp;
    589     } else {
    590         return;
    591     }
    592     record.where = mousePosForPlugin(event);
    593     record.modifiers = modifiersForEvent(event);
    594 
    595     if (!event->buttonDown())
    596         record.modifiers |= btnState;
    597 
    598     if (event->button() == 2)
    599         record.modifiers |= controlKey;
    600 
    601     if (!dispatchNPEvent(record)) {
    602         if (record.what == NPEventType_AdjustCursorEvent)
    603             return; // Signals that the plugin wants a normal cursor
    604 
    605         LOG(Events, "PluginView::handleMouseEvent(): Mouse event type %d at %d,%d not accepted",
     715   
     716#ifndef NP_NO_CARBON
     717    if (m_eventModel != NPEventModelCocoa) {
     718        EventRecord record;
     719       
     720        if (event->type() == eventNames().mousemoveEvent) {
     721            // Mouse movement is handled by null timer events
     722            m_lastMousePos = mousePosForPlugin(event);
     723            return;
     724        } else if (event->type() == eventNames().mouseoverEvent) {
     725            record.what = NPEventType_AdjustCursorEvent;
     726        } else if (event->type() == eventNames().mouseoutEvent) {
     727            record.what = NPEventType_AdjustCursorEvent;
     728        } else if (event->type() == eventNames().mousedownEvent) {
     729            record.what = mouseDown;
     730            // The plugin needs focus to receive keyboard events
     731            if (Page* page = m_parentFrame->page())
     732                page->focusController()->setFocusedFrame(m_parentFrame);
     733            m_parentFrame->document()->setFocusedNode(m_element);
     734        } else if (event->type() == eventNames().mouseupEvent) {
     735            record.what = mouseUp;
     736        } else {
     737            return;
     738        }
     739        record.where = mousePosForPlugin(event);
     740        record.modifiers = modifiersForEvent(event);
     741       
     742        if (!event->buttonDown())
     743            record.modifiers |= btnState;
     744       
     745        if (event->button() == 2)
     746            record.modifiers |= controlKey;
     747       
     748        if (!dispatchNPEvent(record)) {
     749            if (record.what == NPEventType_AdjustCursorEvent)
     750                return; // Signals that the plugin wants a normal cursor
     751           
     752            LOG(Events, "PluginView::handleMouseEvent(): Mouse event type %d at %d,%d not accepted",
    606753                record.what, record.where.h, record.where.v);
    607     } else {
     754        } else {
     755            event->setDefaultHandled();
     756        }
     757    } else
     758#endif
     759    {
     760        NPCocoaEventType eventType;
     761        int32_t buttonNumber = 0;
     762        int32_t clickCount = 0;
     763        NSEvent *currentEvent = [NSApp currentEvent];
     764       
     765        NSEventType type = [currentEvent type];
     766       
     767        switch (type) {
     768            case NSLeftMouseDown:
     769            case NSRightMouseDown:
     770            case NSOtherMouseDown:
     771                buttonNumber = [currentEvent buttonNumber];
     772                clickCount = [currentEvent clickCount];
     773                eventType = NPCocoaEventMouseDown;
     774                // The plugin needs focus to receive keyboard events
     775                if (Page* page = m_parentFrame->page())
     776                    page->focusController()->setFocusedFrame(m_parentFrame);
     777                m_parentFrame->document()->setFocusedNode(m_element);
     778                break;
     779               
     780            case NSLeftMouseUp:
     781            case NSRightMouseUp:
     782            case NSOtherMouseUp:
     783                buttonNumber = [currentEvent buttonNumber];
     784                clickCount = [currentEvent clickCount];
     785                eventType = NPCocoaEventMouseUp;
     786                break;
     787               
     788            case NSMouseMoved:
     789                eventType = NPCocoaEventMouseMoved;
     790                break;
     791               
     792            case NSLeftMouseDragged:
     793            case NSRightMouseDragged:
     794            case NSOtherMouseDragged:
     795                buttonNumber = [currentEvent buttonNumber];
     796                eventType = NPCocoaEventMouseDragged;
     797                break;
     798               
     799            case NSMouseEntered:
     800                eventType = NPCocoaEventMouseEntered;
     801                break;
     802               
     803            case NSMouseExited:
     804                eventType = NPCocoaEventMouseExited;
     805            default:
     806                return;
     807        }
     808       
     809        NPCocoaEvent cocoaEvent;
     810        initializeNPCocoaEvent(&cocoaEvent);
     811       
     812        cocoaEvent.type = eventType;
     813        if (!(NPCocoaEventMouseEntered == eventType || NPCocoaEventMouseExited == eventType)) {
     814            cocoaEvent.data.mouse.buttonNumber = buttonNumber;
     815            cocoaEvent.data.mouse.clickCount = clickCount;
     816        }
     817       
     818        cocoaEvent.data.mouse.pluginX = event->layerX() - m_npWindow.x + m_windowRect.x() - m_element->offsetLeft();
     819        cocoaEvent.data.mouse.pluginY = event->layerY() - m_npWindow.y + m_windowRect.y() - m_element->offsetTop();
     820        cocoaEvent.data.mouse.deltaX = [currentEvent deltaX];
     821        cocoaEvent.data.mouse.deltaY = [currentEvent deltaY];
     822        cocoaEvent.data.mouse.deltaZ = [currentEvent deltaZ];
     823        cocoaEvent.data.mouse.modifierFlags = getModifiers(event);
     824       
     825        int16_t response = dispatchNPCocoaEvent(cocoaEvent);
     826        if(response = kNPEventNotHandled) {
     827            LOG(Events, "PluginView::handleMouseEvent(): Mouse event type %d at %d,%d not accepted", cocoaEvent.type
     828                cocoaEvent.data.mouse.x, cocoaEvent.data.mouse.y);
     829        }
     830       
     831        // Safari policy is to return true for all mouse events, because some plugins
     832        // return false even if they have handled the event.
    608833        event->setDefaultHandled();
    609834    }
    610 #endif
    611 }
    612 
     835}
     836   
    613837void PluginView::handleKeyboardEvent(KeyboardEvent* event)
    614838{
    615839    if (!m_isStarted)
    616840        return;
    617 
    618841    LOG(Plugins, "PluginView::handleKeyboardEvent() ----------------- ");
    619 
     842   
    620843    LOG(Plugins, "PV::hKE(): KE.keyCode: 0x%02X, KE.charCode: %d",
    621             event->keyCode(), event->charCode());
    622 
    623 #ifndef NP_NO_CARBON
    624     EventRecord record;
    625 
    626     if (event->type() == eventNames().keydownEvent) {
    627         // This event is the result of a PlatformEvent::KeyDown which
    628         // was disambiguated into a PlatformKeyboardEvent::RawKeyDown. Since
    629         // we don't have access to the text here, we return, and wait for the
    630         // corresponding event based on PlatformKeyboardEvent::Char.
    631         return;
    632     } else if (event->type() == eventNames().keypressEvent) {
    633         // Which would be this one. This event was disambiguated from the same
    634         // PlatformEvent::KeyDown, but to a PlatformEvent::Char,
    635         // which retains the text from the original event. So, we can safely pass
    636         // on the event as a key-down event to the plugin.
    637         record.what = keyDown;
    638     } else if (event->type() == eventNames().keyupEvent) {
    639         // PlatformEvent::KeyUp events always have the text, so nothing
    640         // fancy here.
    641         record.what = keyUp;
    642     } else {
    643         return;
    644     }
    645 
    646     const PlatformKeyboardEvent* platformEvent = event->keyEvent();
    647     int keyCode = platformEvent->nativeVirtualKeyCode();
    648 
    649     const String text = platformEvent->text();
    650     if (text.length() < 1) {
    651         event->setDefaultHandled();
    652         return;
    653     }
    654 
    655     WTF::RetainPtr<CFStringRef> cfText(WTF::AdoptCF, text.createCFString());
    656 
    657     LOG(Plugins, "PV::hKE(): PKE.text: %s, PKE.unmodifiedText: %s, PKE.keyIdentifier: %s",
     844        event->keyCode(), event->charCode());
     845   
     846#ifndef NP_NO_CARBON
     847    if (m_eventModel != NPEventModelCocoa) {
     848        EventRecord record;
     849        if (event->type() == eventNames().keydownEvent) {
     850            // This event is the result of a PlatformKeyboardEvent::KeyDown which
     851            // was disambiguated into a PlatformKeyboardEvent::RawKeyDown. Since
     852            // we don't have access to the text here, we return, and wait for the
     853            // corresponding event based on PlatformKeyboardEvent::Char.
     854            return;
     855        } else if (event->type() == eventNames().keypressEvent) {
     856            // Which would be this one. This event was disambiguated from the same
     857            // PlatformKeyboardEvent::KeyDown, but to a PlatformKeyboardEvent::Char,
     858            // which retains the text from the original event. So, we can safely pass
     859            // on the event as a key-down event to the plugin.
     860            record.what = keyDown;
     861        } else if (event->type() == eventNames().keyupEvent) {
     862            // PlatformKeyboardEvent::KeyUp events always have the text, so nothing
     863            // fancy here.
     864            record.what = keyUp;
     865        } else {
     866            return;
     867        }
     868       
     869        const PlatformKeyboardEvent* platformEvent = event->keyEvent();
     870        int keyCode = platformEvent->nativeVirtualKeyCode();
     871       
     872        const String text = platformEvent->text();
     873        if (text.length() < 1) {
     874            event->setDefaultHandled();
     875            return;
     876        }
     877       
     878        WTF::RetainPtr<CFStringRef> cfText(WTF::AdoptCF, text.createCFString());
     879       
     880        LOG(Plugins, "PV::hKE(): PKE.text: %s, PKE.unmodifiedText: %s, PKE.keyIdentifier: %s",
    658881            text.ascii().data(), platformEvent->unmodifiedText().ascii().data(),
    659882            platformEvent->keyIdentifier().ascii().data());
    660 
    661     char charCodes[2] = { 0, 0 };
    662     if (!CFStringGetCString(cfText.get(), charCodes, 2, CFStringGetSystemEncoding())) {
    663         LOG_ERROR("Could not resolve character code using system encoding.");
    664         event->setDefaultHandled();
    665         return;
    666     }
    667 
    668     record.where = globalMousePosForPlugin();
    669     record.modifiers = modifiersForEvent(event);
    670     record.message = ((keyCode & 0xFF) << 8) | (charCodes[0] & 0xFF);
    671     record.when = TickCount();
    672 
    673     LOG(Plugins, "PV::hKE(): record.modifiers: %d", record.modifiers);
    674 
     883       
     884        char charCodes[2] = { 0, 0 };
     885        if (!CFStringGetCString(cfText.get(), charCodes, 2, CFStringGetSystemEncoding())) {
     886            LOG_ERROR("Could not resolve character code using system encoding.");
     887            event->setDefaultHandled();
     888            return;
     889        }
     890       
     891        record.where = globalMousePosForPlugin();
     892        record.modifiers = modifiersForEvent(event);
     893        record.message = ((keyCode & 0xFF) << 8) | (charCodes[0] & 0xFF);
     894        record.when = TickCount();
     895       
     896        LOG(Plugins, "PV::hKE(): record.modifiers: %d", record.modifiers);
     897       
    675898#if PLATFORM(QT)
    676     LOG(Plugins, "PV::hKE(): PKE.qtEvent()->nativeVirtualKey: 0x%02X, charCode: %d",
    677                keyCode, int(uchar(charCodes[0])));
    678 #endif
    679 
    680     if (!dispatchNPEvent(record))
    681         LOG(Events, "PluginView::handleKeyboardEvent(): Keyboard event type %d not accepted", record.what);
    682     else
    683         event->setDefaultHandled();
    684 #endif
    685 }
    686 
     899        LOG(Plugins, "PV::hKE(): PKE.qtEvent()->nativeVirtualKey: 0x%02X, charCode: %d",
     900            keyCode, int(uchar(charCodes[0])));
     901#endif
     902       
     903        if (!dispatchNPEvent(record))
     904            LOG(Events, "PluginView::handleKeyboardEvent(): Keyboard event type %d not accepted", record.what);
     905        else
     906            event->setDefaultHandled();
     907    } else
     908#endif
     909    {
     910        NSEvent *currentEvent = [NSApp currentEvent];
     911        NPCocoaEventType eventType;
     912        NSEventType type = [currentEvent type];
     913       
     914        switch (type) {
     915            case NSKeyDown:
     916                eventType = NPCocoaEventKeyDown;
     917                m_keyDownSent = true;
     918                break;
     919            case NSKeyUp:
     920                if (m_disregardKeyUpCounter > 0) {
     921                    m_disregardKeyUpCounter--;
     922                    event->setDefaultHandled();
     923                    return;
     924                }
     925                eventType = NPCocoaEventKeyUp;
     926                break;
     927            case NSFlagsChanged:
     928                eventType = NPCocoaEventFlagsChanged;
     929                break;
     930            default:
     931                return;
     932        }
     933       
     934        NPCocoaEvent cocoaEvent;
     935        initializeNPCocoaEvent(&cocoaEvent);
     936        cocoaEvent.type = eventType;
     937        if (eventType != NPCocoaEventFlagsChanged) {
     938            NSString *characters = [currentEvent characters];
     939            NSString *charactersIgnoringModifiers = [currentEvent charactersIgnoringModifiers];
     940            cocoaEvent.data.key.characters = reinterpret_cast<NPNSString*>(characters);
     941            cocoaEvent.data.key.charactersIgnoringModifiers = reinterpret_cast<NPNSString*>(charactersIgnoringModifiers);
     942            cocoaEvent.data.key.isARepeat = [currentEvent isARepeat];
     943            cocoaEvent.data.key.keyCode = [currentEvent keyCode];
     944            cocoaEvent.data.key.modifierFlags = getModifiers(event);
     945        }
     946       
     947        int16_t response = dispatchNPCocoaEvent(cocoaEvent);
     948        if(response == kNPEventNotHandled) {
     949            LOG(Events, "PluginView::handleKeyboardEvent(): Keyboard event type %d not accepted", cocoaEvent.type);
     950        } else if (response == kNPEventStartIME) {
     951            // increment counter and resend as a text input
     952            m_disregardKeyUpCounter++;
     953            NPCocoaEvent textEvent;
     954            initializeNPCocoaEvent(&textEvent);
     955            textEvent.type = NPCocoaEventTextInput;
     956            textEvent.data.text.text = reinterpret_cast<NPNSString*>([currentEvent characters]);
     957            response = dispatchNPCocoaEvent(textEvent);
     958            if(response == kNPEventNotHandled)
     959                LOG(Events, "PluginView::handleKeyboardEvent(): Keyboard event type %d not accepted", cocoaEvent.type);
     960        }
     961       
     962        // All keyboard events need to be handled to prevent them falling
     963        // through to the page, unless they are Meta key events, in which
     964        // case they are, unless they are Cmd+a. From WebKit2, possibly
     965        // not the most elegant piece of key handling code.....
     966        if (event->metaKey()) {
     967            if (cocoaEvent.data.key.keyCode == 0)
     968                event->setDefaultHandled();
     969        } else {
     970            // else ignore, it's a Meta Key event for the browser.
     971            event->setDefaultHandled();
     972        }
     973    }
     974}
     975   
    687976#ifndef NP_NO_CARBON
    688977void PluginView::nullEventTimerFired(Timer<PluginView>*)
     
    7831072#endif
    7841073
     1074
     1075int16_t PluginView::dispatchNPCocoaEvent(NPCocoaEvent& cocoaEvent)
     1076{
     1077    PluginView::setCurrentPluginView(this);
     1078    JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonJSGlobalData());
     1079    setCallingPlugin(true);
     1080
     1081    int16_t response = m_plugin->pluginFuncs()->event(m_instance, &cocoaEvent);
     1082
     1083    setCallingPlugin(false);
     1084    PluginView::setCurrentPluginView(0);
     1085
     1086    return response;
     1087}
     1088
    7851089// ------------------- Miscellaneous  ------------------
    7861090
  • trunk/Source/WebCore/plugins/npapi.cpp

    r130353 r136124  
    200200    return pluginViewForInstance(instance)->getAuthenticationInfo(protocol, host, port, scheme, realm, username, ulen, password, plen);
    201201}
     202
     203NPError NPN_PopUpContextMenu(NPP instance, NPMenu* menu)
     204{
     205#if PLATFORM(QT) && defined(XP_MACOSX)
     206    PluginView* plugin = pluginViewForInstance(instance);
     207    plugin->popUpContextMenu(menu);
     208    return NPERR_NO_ERROR;
     209#else
     210    return NPERR_NO_ERROR;
     211#endif // PLATFORM(QT) && defined(XP_MACOSX)
     212}
  • trunk/Source/WebCore/plugins/npapi.h

    r114869 r136124  
    416416  NPNVSupportsWindowless = 17,
    417417
    418   NPNVprivateModeBool = 18
     418  NPNVprivateModeBool = 18,
     419
     420  NPNVsupportsAdvancedKeyHandling = 21
    419421
    420422#if defined(XP_MACOSX)
Note: See TracChangeset for help on using the changeset viewer.