Changeset 51234 in webkit


Ignore:
Timestamp:
Nov 20, 2009 3:18:31 AM (14 years ago)
Author:
Girish Ramakrishnan
Message:

[Qt] Implement support for rendering plugins on Qt/Mac when a page is used
without a QWebView or when inside QGraphicsWebView.

Reviewed by Simon Hausmann.

Patch by Yongjun Zhang <yongjun.zhang@nokia.com> and

Girish Ramakrishnan <Girish Ramakrishnan>

Currently, the code provides the cgcontext of the PlatformPluginWidget to
the plugin. This approach does not work when we are printing, or using
QWebFrame::render() to render to a QImage/QPixmap since the plugin ends
up drawing on the QWebView (i.e platformPluginWidget's cgcontext) instead
of the QPaintDevice's context.

To solve all cases and keep the code simple, we render the plugin to an
offscreen pixmap in all cases. This way, the plugin always renders to the
CGContext of the pixmap and we then use QPainter to blit the pixmap into
the QPaintDevice. We also create a fake window and set it's WindowRef in
NPWindow. Only with this WindowRef does Flash paint correctly to the QPixmap.

Now, that's the theory. In practice, ATM, mouse events do not work when using
the fake window. So, setPlatformPluginWidget() is still called when using QWebView
so that there are no regressions after this patch. Once we get mouse events
working, setPlatformPluginWidget will be removed.

https://bugs.webkit.org/show_bug.cgi?id=31183

Location:
trunk/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r51229 r51234  
     12009-11-18  Girish Ramakrishnan  <girish@forwardbias.in>
     2
     3        Reviewed by Simon Hausmann.
     4
     5        Patch by Yongjun Zhang <yongjun.zhang@nokia.com> and
     6                 Girish Ramakrishnan <girish@forwardbias.in>
     7       
     8        [Qt] Implement support for rendering plugins on Qt/Mac when a page is used
     9        without a QWebView or when inside QGraphicsWebView.
     10       
     11        Currently, the code provides the cgcontext of the PlatformPluginWidget to
     12        the plugin. This approach does not work when we are printing, or using
     13        QWebFrame::render() to render to a QImage/QPixmap since the plugin ends
     14        up drawing on the QWebView (i.e platformPluginWidget's cgcontext) instead
     15        of the QPaintDevice's context.
     16       
     17        To solve all cases and keep the code simple, we render the plugin to an
     18        offscreen pixmap in all cases. This way, the plugin always renders to the
     19        CGContext of the pixmap and we then use QPainter to blit the pixmap into
     20        the QPaintDevice. We also create a fake window and set it's WindowRef in
     21        NPWindow. Only with this WindowRef does Flash paint correctly to the QPixmap.
     22       
     23        Now, that's the theory. In practice, ATM, mouse events do not work when using
     24        the fake window. So, setPlatformPluginWidget() is still called when using QWebView
     25        so that there are no regressions after this patch. Once we get mouse events
     26        working, setPlatformPluginWidget will be removed.
     27       
     28        https://bugs.webkit.org/show_bug.cgi?id=31183
     29
     30        * plugins/PluginView.cpp:
     31        (WebCore::PluginView::PluginView):
     32        * plugins/PluginView.h:
     33        * plugins/mac/PluginViewMac.cpp:
     34        (WebCore::PluginView::platformStart):
     35        (WebCore::PluginView::platformDestroy):
     36        (WebCore::PluginView::setNPWindowIfNeeded):
     37        (WebCore::PluginView::updatePluginWidget):
     38        (WebCore::PluginView::paint):
     39        (WebCore::PluginView::invalidateRect):
     40
    1412009-11-19  Joseph Pecoraro  <joepeck@webkit.org>
    242
  • trunk/WebCore/plugins/PluginView.cpp

    r51215 r51234  
    816816    , m_drawingModel(NPDrawingModel(-1))
    817817    , m_eventModel(NPEventModel(-1))
     818    , m_contextRef(0)
     819    , m_fakeWindow(0)
    818820#endif
    819821#if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API)
  • trunk/WebCore/plugins/PluginView.h

    r51143 r51234  
    22 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
    33 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
     4 * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
    45 *
    56 * Redistribution and use in source and binary forms, with or without
     
    5152#else
    5253typedef PlatformWidget PlatformPluginWidget;
     54#if defined(XP_MACOSX) && PLATFORM(QT)
     55#include <QPixmap>
     56#endif
    5357#endif
    5458
     
    327331        NPDrawingModel m_drawingModel;
    328332        NPEventModel m_eventModel;
     333        CGContextRef m_contextRef;
     334        WindowRef m_fakeWindow;
     335#if PLATFORM(QT)
     336        QPixmap m_pixmap;
     337#endif
    329338
    330339        void setNPWindowIfNeeded();
  • trunk/WebCore/plugins/mac/PluginViewMac.cpp

    r51105 r51234  
    33 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
    44 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
     5 * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
    56 *
    67 * Redistribution and use in source and binary forms, with or without
     
    7677#include <QWidget>
    7778#include <QKeyEvent>
     79#include <QPainter>
    7880#include "QWebPageClient.h"
    7981QT_BEGIN_NAMESPACE
     
    174176
    175177#if PLATFORM(QT)
     178    // Set the platformPluginWidget only in the case of QWebView until we get mouse events working.
     179    // In all other cases, we use off-screen rendering
    176180    if (QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient()) {
    177         if (QWidget* widget = client->ownerWidget()) {
     181        if (QWidget* widget = qobject_cast<QWidget*>(client->pluginParent()))
    178182            setPlatformPluginWidget(widget);
    179         }
    180     }
    181 #endif
     183    }
     184#endif
     185
     186    // Create a fake window relative to which all events will be sent when using offscreen rendering
     187    if (!platformPluginWidget()) {
     188        ::Rect windowBounds = { 0, 0, 100, 100 };
     189        CreateNewWindow(kDocumentWindowClass, kWindowStandardDocumentAttributes, &windowBounds, &m_fakeWindow);
     190    }
    182191
    183192    show();
     
    190199    if (platformPluginWidget())
    191200        setPlatformPluginWidget(0);
     201    else {
     202        CGContextRelease(m_contextRef);
     203        if (m_fakeWindow)
     204            DisposeWindow(m_fakeWindow);
     205    }
    192206}
    193207
     
    354368        return;
    355369
    356     CGContextRef newContextRef = cgHandleFor(platformPluginWidget());
    357     if (!newContextRef)
    358         return;
    359 
    360     WindowRef newWindowRef = nativeWindowFor(platformPluginWidget());
    361     if (!newWindowRef)
    362         return;
    363 
    364     m_npWindow.type = NPWindowTypeWindow;
     370    CGContextRef newContextRef = 0;
     371    WindowRef newWindowRef = 0;
     372    if (platformPluginWidget()) {
     373        newContextRef = cgHandleFor(platformPluginWidget());
     374        newWindowRef = nativeWindowFor(platformPluginWidget());
     375        m_npWindow.type = NPWindowTypeWindow;
     376    } else {
     377        newContextRef = m_contextRef;
     378        newWindowRef = m_fakeWindow;
     379        m_npWindow.type = NPWindowTypeDrawable;
     380    }
     381
     382    if (!newContextRef || !newWindowRef)
     383        return;
     384
    365385    m_npWindow.window = (void*)&m_npCgContext;
    366386    m_npCgContext.window = newWindowRef;
     
    406426    m_windowRect.move(offset.x(), offset.y());
    407427
     428    if (!platformPluginWidget()) {
     429        if (m_windowRect.size() != oldWindowRect.size()) {
     430            CGContextRelease(m_contextRef);
     431#if PLATFORM(QT)
     432            m_pixmap = QPixmap(m_windowRect.size());
     433            m_pixmap.fill(Qt::transparent);
     434            m_contextRef = qt_mac_cg_context(&m_pixmap);
     435#endif
     436        }
     437    }
     438
    408439    m_clipRect = windowClipRect();
    409440    m_clipRect.move(-m_windowRect.x(), -m_windowRect.y());
     
    430461
    431462    CGContextSaveGState(cgContext);
    432     IntPoint offset = frameRect().location();
    433     CGContextTranslateCTM(cgContext, offset.x(), offset.y());
     463    if (platformPluginWidget()) {
     464        IntPoint offset = frameRect().location();
     465        CGContextTranslateCTM(cgContext, offset.x(), offset.y());
     466    }
     467
     468    IntRect targetRect(frameRect());
     469    targetRect.intersects(rect);
     470
     471    // clip the context so that plugin only updates the interested area.
     472    CGRect r;
     473    r.origin.x = targetRect.x() - frameRect().x();
     474    r.origin.y = targetRect.y() - frameRect().y();
     475    r.size.width = targetRect.width();
     476    r.size.height = targetRect.height();
     477    CGContextClipToRect(cgContext, r);
     478
     479    if (!platformPluginWidget() && m_isTransparent) { // clean the pixmap in transparent mode
     480#if PLATFORM(QT)
     481        QPainter painter(&m_pixmap);
     482        painter.setCompositionMode(QPainter::CompositionMode_Clear);
     483        painter.fillRect(QRectF(r.origin.x, r.origin.y, r.size.width, r.size.height), Qt::transparent);
     484#endif
     485    }
    434486
    435487    EventRecord event;
     
    445497
    446498    CGContextRestoreGState(cgContext);
     499
     500    if (!platformPluginWidget()) {
     501#if PLATFORM(QT)
     502        QPainter* painter = context->platformContext();
     503        painter->drawPixmap(targetRect.x(), targetRect.y(), m_pixmap,
     504                            targetRect.x() - frameRect().x(), targetRect.y() - frameRect().y(), targetRect.width(), targetRect.height());
     505#endif
     506    }
    447507}
    448508
     
    451511    if (platformPluginWidget())
    452512        platformPluginWidget()->update(convertToContainingWindow(rect));
     513    else
     514        invalidateWindowlessPluginRect(rect);
    453515}
    454516
    455517void PluginView::invalidateRect(NPRect* rect)
    456518{
    457     // TODO: optimize
    458     invalidate();
     519    IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top);
     520    invalidateRect(r);
    459521}
    460522
Note: See TracChangeset for help on using the changeset viewer.