Changeset 53955 in webkit


Ignore:
Timestamp:
Jan 27, 2010 3:16:04 PM (14 years ago)
Author:
eric@webkit.org
Message:

2010-01-27 Brian Tarricone <brian@kakai.com>

Reviewed by Gustavo Noronha Silva.

[gtk] Add support for windowless NPAPI plugins

Much of this is a translation of how the Qt backend does this,
modified for Gtk.

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

No new tests; there is already a windowless test in the tree.

  • plugins/PluginView.cpp: (WebCore::PluginView::handleEvent): (WebCore::PluginView::PluginView):
  • plugins/PluginView.h:
  • plugins/gtk/PluginViewGtk.cpp: (WebCore::getRootWindow): (WebCore::PluginView::updatePluginWidget): (WebCore::PluginView::paint): (WebCore::PluginView::handleKeyboardEvent): (WebCore::inputEventState): (WebCore::PluginView::initXEvent): (WebCore::setXButtonEventSpecificFields): (WebCore::setXMotionEventSpecificFields): (WebCore::setXCrossingEventSpecificFields): (WebCore::PluginView::handleMouseEvent): (WebCore::PluginView::handleFocusInEvent): (WebCore::PluginView::handleFocusOutEvent): (WebCore::PluginView::setNPWindowRect): (WebCore::PluginView::setNPWindowIfNeeded): (WebCore::PluginView::getValueStatic): (WebCore::PluginView::invalidateRect): (WebCore::getPluginDisplay): (WebCore::plug_removed_cb): (WebCore::getVisualAndColormap): (WebCore::PluginView::platformStart): (WebCore::PluginView::platformDestroy):
Location:
trunk/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r53953 r53955  
     12010-01-27  Brian Tarricone  <brian@kakai.com>
     2
     3        Reviewed by Gustavo Noronha Silva.
     4
     5        [gtk] Add support for windowless NPAPI plugins
     6
     7        Much of this is a translation of how the Qt backend does this,
     8        modified for Gtk.
     9
     10        https://bugs.webkit.org/show_bug.cgi?id=18831
     11
     12        No new tests; there is already a windowless test in the tree.
     13
     14        * plugins/PluginView.cpp:
     15        (WebCore::PluginView::handleEvent):
     16        (WebCore::PluginView::PluginView):
     17        * plugins/PluginView.h:
     18        * plugins/gtk/PluginViewGtk.cpp:
     19        (WebCore::getRootWindow):
     20        (WebCore::PluginView::updatePluginWidget):
     21        (WebCore::PluginView::paint):
     22        (WebCore::PluginView::handleKeyboardEvent):
     23        (WebCore::inputEventState):
     24        (WebCore::PluginView::initXEvent):
     25        (WebCore::setXButtonEventSpecificFields):
     26        (WebCore::setXMotionEventSpecificFields):
     27        (WebCore::setXCrossingEventSpecificFields):
     28        (WebCore::PluginView::handleMouseEvent):
     29        (WebCore::PluginView::handleFocusInEvent):
     30        (WebCore::PluginView::handleFocusOutEvent):
     31        (WebCore::PluginView::setNPWindowRect):
     32        (WebCore::PluginView::setNPWindowIfNeeded):
     33        (WebCore::PluginView::getValueStatic):
     34        (WebCore::PluginView::invalidateRect):
     35        (WebCore::getPluginDisplay):
     36        (WebCore::plug_removed_cb):
     37        (WebCore::getVisualAndColormap):
     38        (WebCore::PluginView::platformStart):
     39        (WebCore::PluginView::platformDestroy):
     40
    1412010-01-27  Anton Muhin  <antonm@chromium.org>
    242
  • trunk/WebCore/plugins/PluginView.cpp

    r53581 r53955  
    153153    else if (event->isKeyboardEvent())
    154154        handleKeyboardEvent(static_cast<KeyboardEvent*>(event));
    155 #if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API)
     155#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
    156156    else if (event->type() == eventNames().DOMFocusOutEvent)
    157157        handleFocusOutEvent();
     
    805805    , m_haveInitialized(false)
    806806    , m_isWaitingToStart(false)
    807 #if defined(XP_UNIX) || defined(Q_WS_X11)
     807#if defined(XP_UNIX)
    808808    , m_needsXEmbed(false)
    809809#endif
     
    824824    , m_fakeWindow(0)
    825825#endif
    826 #if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API)
     826#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
    827827    , m_hasPendingGeometryChange(true)
    828828    , m_drawable(0)
  • trunk/WebCore/plugins/PluginView.h

    r52791 r53955  
    266266        void handleKeyboardEvent(KeyboardEvent*);
    267267        void handleMouseEvent(MouseEvent*);
    268 #if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API)
     268#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
    269269        void handleFocusInEvent();
    270270        void handleFocusOutEvent();
     
    299299        bool m_isWaitingToStart;
    300300
    301 #if defined(XP_UNIX) || defined(Q_WS_X11)
     301#if defined(XP_UNIX)
    302302        bool m_needsXEmbed;
    303303#endif
     
    327327private:
    328328
    329 #if defined(XP_UNIX) || defined(Q_WS_X11) || OS(SYMBIAN)
     329#if defined(XP_UNIX) || PLATFORM(SYMBIAN)
    330330        void setNPWindowIfNeeded();
    331331#elif defined(XP_MACOSX)
     
    343343#endif
    344344
    345 #if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API)
     345#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
    346346        bool m_hasPendingGeometryChange;
    347347        Pixmap m_drawable;
  • trunk/WebCore/plugins/gtk/PluginViewGtk.cpp

    r53464 r53955  
    22 * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
    33 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
     4 * Copyright (C) 2009, 2010 Kakai, Inc. <brian@kakai.com>
    45 *
    56 * Redistribution and use in source and binary forms, with or without
     
    4546#include "MouseEvent.h"
    4647#include "Page.h"
     48#include "PlatformKeyboardEvent.h"
    4749#include "PlatformMouseEvent.h"
    4850#include "PluginDebug.h"
     
    6365#if defined(XP_UNIX)
    6466#include "gtk2xtbin.h"
     67#define Bool int // this got undefined somewhere
     68#define Status int // ditto
     69#include <X11/extensions/Xrender.h>
     70#include <cairo/cairo-xlib.h>
    6571#include <gdk/gdkx.h>
    6672#elif defined(GDK_WINDOWING_WIN32)
     
    100106}
    101107
     108#if defined(XP_UNIX)
     109static Window getRootWindow(Frame* parentFrame)
     110{
     111    GtkWidget* parentWidget = parentFrame->view()->hostWindow()->platformPageClient();
     112    GdkScreen* gscreen = gtk_widget_get_screen(parentWidget);
     113    return GDK_WINDOW_XWINDOW(gdk_screen_get_root_window(gscreen));
     114}
     115#endif
     116
    102117void PluginView::updatePluginWidget()
    103118{
    104     if (!parent() || !m_isWindowed)
     119    if (!parent())
    105120        return;
    106121
     
    117132    if (platformPluginWidget() && (m_windowRect != oldWindowRect || m_clipRect != oldClipRect))
    118133        setNPWindowIfNeeded();
     134
     135#if defined(XP_UNIX)
     136    if (!m_isWindowed && m_windowRect.size() != oldWindowRect.size()) {
     137        if (m_drawable)
     138            XFreePixmap(GDK_DISPLAY(), m_drawable);
     139
     140        m_drawable = XCreatePixmap(GDK_DISPLAY(), getRootWindow(m_parentFrame),
     141                                   m_windowRect.width(), m_windowRect.height(),
     142                                   ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth);
     143        XSync(GDK_DISPLAY(), False); // make sure that the server knows about the Drawable
     144    }
     145
     146    // do not call setNPWindowIfNeeded() immediately, will be called on paint()
     147    m_hasPendingGeometryChange = true;
     148#endif
     149
     150    // In order to move/resize the plugin window at the same time as the
     151    // rest of frame during e.g. scrolling, we set the window geometry
     152    // in the paint() function, but as paint() isn't called when the
     153    // plugin window is outside the frame which can be caused by a
     154    // scroll, we need to move/resize immediately.
     155    if (!m_windowRect.intersects(frameView->frameRect()))
     156        setNPWindowIfNeeded();
    119157}
    120158
     
    162200        return;
    163201
    164     NPEvent npEvent;
    165     /* Need to synthesize Xevents here */
    166 
    167     m_npWindow.type = NPWindowTypeDrawable;
    168 
    169     ASSERT(parent()->isFrameView());
    170 
    171     if (!dispatchNPEvent(npEvent))
    172         LOG(Events, "PluginView::paint(): Paint event not accepted");
     202#if defined(XP_UNIX)
     203    if (!m_drawable)
     204        return;
     205
     206    const bool syncX = m_pluginDisplay && m_pluginDisplay != GDK_DISPLAY();
     207
     208    IntRect exposedRect(rect);
     209    exposedRect.intersect(frameRect());
     210    exposedRect.move(-frameRect().x(), -frameRect().y());
     211
     212    Window dummyW;
     213    int dummyI;
     214    unsigned int dummyUI, actualDepth = 0;
     215    XGetGeometry(GDK_DISPLAY(), m_drawable, &dummyW, &dummyI, &dummyI,
     216                 &dummyUI, &dummyUI, &dummyUI, &actualDepth);
     217
     218    const int drawableDepth = ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth;
     219    ASSERT(drawableDepth == actualDepth);
     220
     221    cairo_surface_t* drawableSurface = cairo_xlib_surface_create(GDK_DISPLAY(),
     222                                                                 m_drawable,
     223                                                                 m_visual,
     224                                                                 m_windowRect.width(),
     225                                                                 m_windowRect.height());
     226
     227    if (m_isTransparent && drawableDepth != 32) {
     228        // Attempt to fake it when we don't have an alpha channel on our
     229        // pixmap.  If that's not possible, at least clear the window to
     230        // avoid drawing artifacts.
     231        GtkWidget* widget = m_parentFrame->view()->hostWindow()->platformPageClient();
     232        GdkDrawable* gdkBackingStore = 0;
     233        gint xoff = 0, yoff = 0;
     234
     235        gdk_window_get_internal_paint_info(widget->window, &gdkBackingStore, &xoff, &yoff);
     236
     237        GC gc = XDefaultGC(GDK_DISPLAY(), gdk_screen_get_number(gdk_screen_get_default()));
     238        if (gdkBackingStore) {
     239            XCopyArea(GDK_DISPLAY(), GDK_DRAWABLE_XID(gdkBackingStore), m_drawable, gc,
     240                      m_windowRect.x() + exposedRect.x() - xoff,
     241                      m_windowRect.y() + exposedRect.y() - yoff,
     242                      exposedRect.width(), exposedRect.height(),
     243                      exposedRect.x(), exposedRect.y());
     244        } else {
     245            // no valid backing store; clear to the background color
     246            XFillRectangle(GDK_DISPLAY(), m_drawable, gc,
     247                           exposedRect.x(), exposedRect.y(),
     248                           exposedRect.width(), exposedRect.height());
     249        }
     250    } else if (m_isTransparent) {
     251        // If we have a 32 bit drawable and the plugin wants transparency,
     252        // we'll clear the exposed area to transparent first.  Otherwise,
     253        // we'd end up with junk in there from the last paint, or, worse,
     254        // uninitialized data.
     255        cairo_t* crFill = cairo_create(drawableSurface);
     256
     257        cairo_set_operator(crFill, CAIRO_OPERATOR_SOURCE);
     258        cairo_pattern_t* fill = cairo_pattern_create_rgba(0., 0., 0., 0.);
     259        cairo_set_source(crFill, fill);
     260
     261        cairo_rectangle(crFill, exposedRect.x(), exposedRect.y(),
     262                        exposedRect.width(), exposedRect.height());
     263        cairo_clip(crFill);
     264        cairo_paint(crFill);
     265
     266        cairo_destroy(crFill);
     267        cairo_pattern_destroy(fill);
     268    }
     269
     270    XEvent xevent;
     271    memset(&xevent, 0, sizeof(XEvent));
     272    XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose;
     273    exposeEvent.type = GraphicsExpose;
     274    exposeEvent.display = GDK_DISPLAY();
     275    exposeEvent.drawable = m_drawable;
     276    exposeEvent.x = exposedRect.x();
     277    exposeEvent.y = exposedRect.y();
     278    exposeEvent.width = exposedRect.x() + exposedRect.width(); // flash bug? it thinks width is the right in transparent mode
     279    exposeEvent.height = exposedRect.y() + exposedRect.height(); // flash bug? it thinks height is the bottom in transparent mode
     280
     281    dispatchNPEvent(xevent);
     282
     283    if (syncX)
     284        XSync(m_pluginDisplay, False); // sync changes by plugin
     285
     286    cairo_t* cr = context->platformContext();
     287    cairo_save(cr);
     288
     289    cairo_set_source_surface(cr, drawableSurface, frameRect().x(), frameRect().y());
     290
     291    cairo_rectangle(cr,
     292                    frameRect().x() + exposedRect.x(), frameRect().y() + exposedRect.y(),
     293                    exposedRect.width(), exposedRect.height());
     294    cairo_clip(cr);
     295
     296    if (m_isTransparent)
     297        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
     298    else
     299        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
     300    cairo_paint(cr);
     301
     302    cairo_restore(cr);
     303    cairo_surface_destroy(drawableSurface);
     304#endif // defined(XP_UNIX)
    173305}
    174306
    175307void PluginView::handleKeyboardEvent(KeyboardEvent* event)
    176308{
    177     NPEvent npEvent;
    178    
    179     /* FIXME: Synthesize an XEvent to pass through */
    180 
    181309    JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
    182     if (!dispatchNPEvent(npEvent))
     310
     311    if (m_isWindowed)
     312        return;
     313
     314    if (event->type() != eventNames().keydownEvent && event->type() != eventNames().keyupEvent)
     315        return;
     316
     317    NPEvent xEvent;
     318#if defined(XP_UNIX)
     319    GdkEventKey* gdkEvent = event->keyEvent()->gdkEventKey();
     320
     321    xEvent.type = (event->type() == eventNames().keydownEvent) ? 2 : 3; // KeyPress/Release get unset somewhere
     322    xEvent.xkey.root = getRootWindow(m_parentFrame);
     323    xEvent.xkey.subwindow = 0; // we have no child window
     324    xEvent.xkey.time = event->timeStamp();
     325    xEvent.xkey.state = gdkEvent->state; // GdkModifierType mirrors xlib state masks
     326    xEvent.xkey.keycode = gdkEvent->hardware_keycode;
     327    xEvent.xkey.same_screen = true;
     328
     329    // NOTE: As the XEvents sent to the plug-in are synthesized and there is not a native window
     330    // corresponding to the plug-in rectangle, some of the members of the XEvent structures are not
     331    // set to their normal Xserver values. e.g. Key events don't have a position.
     332    // source: https://developer.mozilla.org/en/NPEvent
     333    xEvent.xkey.x = 0;
     334    xEvent.xkey.y = 0;
     335    xEvent.xkey.x_root = 0;
     336    xEvent.xkey.y_root = 0;
     337#endif
     338
     339    if (!dispatchNPEvent(xEvent))
    183340        event->setDefaultHandled();
    184341}
    185342
     343#if defined(XP_UNIX)
     344static unsigned int inputEventState(MouseEvent* event)
     345{
     346    unsigned int state = 0;
     347    if (event->ctrlKey())
     348        state |= ControlMask;
     349    if (event->shiftKey())
     350        state |= ShiftMask;
     351    if (event->altKey())
     352        state |= Mod1Mask;
     353    if (event->metaKey())
     354        state |= Mod4Mask;
     355    return state;
     356}
     357
     358void PluginView::initXEvent(XEvent* xEvent)
     359{
     360    memset(xEvent, 0, sizeof(XEvent));
     361
     362    xEvent->xany.serial = 0; // we are unaware of the last request processed by X Server
     363    xEvent->xany.send_event = false;
     364    xEvent->xany.display = GDK_DISPLAY();
     365    // NOTE: event->xany.window doesn't always correspond to the .window property of other XEvent's
     366    // but does in the case of KeyPress, KeyRelease, ButtonPress, ButtonRelease, and MotionNotify
     367    // events; thus, this is right:
     368    GtkWidget* widget = m_parentFrame->view()->hostWindow()->platformPageClient();
     369    xEvent->xany.window = widget ? GDK_WINDOW_XWINDOW(widget->window) : 0;
     370}
     371
     372static void setXButtonEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos, Frame* parentFrame)
     373{
     374    XButtonEvent& xbutton = xEvent->xbutton;
     375    xbutton.type = event->type() == eventNames().mousedownEvent ? ButtonPress : ButtonRelease;
     376    xbutton.root = getRootWindow(parentFrame);
     377    xbutton.subwindow = 0;
     378    xbutton.time = event->timeStamp();
     379    xbutton.x = postZoomPos.x();
     380    xbutton.y = postZoomPos.y();
     381    xbutton.x_root = event->screenX();
     382    xbutton.y_root = event->screenY();
     383    xbutton.state = inputEventState(event);
     384    switch (event->button()) {
     385    case MiddleButton:
     386        xbutton.button = Button2;
     387        break;
     388    case RightButton:
     389        xbutton.button = Button3;
     390        break;
     391    case LeftButton:
     392    default:
     393        xbutton.button = Button1;
     394        break;
     395    }
     396    xbutton.same_screen = true;
     397}
     398
     399static void setXMotionEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos, Frame* parentFrame)
     400{
     401    XMotionEvent& xmotion = xEvent->xmotion;
     402    xmotion.type = MotionNotify;
     403    xmotion.root = getRootWindow(parentFrame);
     404    xmotion.subwindow = 0;
     405    xmotion.time = event->timeStamp();
     406    xmotion.x = postZoomPos.x();
     407    xmotion.y = postZoomPos.y();
     408    xmotion.x_root = event->screenX();
     409    xmotion.y_root = event->screenY();
     410    xmotion.state = inputEventState(event);
     411    xmotion.is_hint = NotifyNormal;
     412    xmotion.same_screen = true;
     413}
     414
     415static void setXCrossingEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos, Frame* parentFrame)
     416{
     417    XCrossingEvent& xcrossing = xEvent->xcrossing;
     418    xcrossing.type = event->type() == eventNames().mouseoverEvent ? EnterNotify : LeaveNotify;
     419    xcrossing.root = getRootWindow(parentFrame);
     420    xcrossing.subwindow = 0;
     421    xcrossing.time = event->timeStamp();
     422    xcrossing.x = postZoomPos.y();
     423    xcrossing.y = postZoomPos.x();
     424    xcrossing.x_root = event->screenX();
     425    xcrossing.y_root = event->screenY();
     426    xcrossing.state = inputEventState(event);
     427    xcrossing.mode = NotifyNormal;
     428    xcrossing.detail = NotifyDetailNone;
     429    xcrossing.same_screen = true;
     430    xcrossing.focus = false;
     431}
     432#endif
     433
    186434void PluginView::handleMouseEvent(MouseEvent* event)
    187435{
    188     NPEvent npEvent;
    189 
    190     if (!m_isWindowed)
    191       return;
    192 
    193     /* FIXME: Synthesize an XEvent to pass through */
    194     IntPoint p = static_cast<FrameView*>(parent())->contentsToWindow(IntPoint(event->pageX(), event->pageY()));
    195 
    196436    JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
    197     if (!dispatchNPEvent(npEvent))
     437
     438    if (m_isWindowed)
     439        return;
     440
     441    NPEvent xEvent;
     442#if defined(XP_UNIX)
     443    initXEvent(&xEvent);
     444
     445    IntPoint postZoomPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation()));
     446
     447    if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent)
     448        setXButtonEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame);
     449    else if (event->type() == eventNames().mousemoveEvent)
     450        setXMotionEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame);
     451    else if (event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mouseoverEvent)
     452        setXCrossingEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame);
     453    else
     454        return;
     455#endif
     456
     457    if (!dispatchNPEvent(xEvent))
    198458        event->setDefaultHandled();
    199459}
     460
     461#if defined(XP_UNIX)
     462void PluginView::handleFocusInEvent()
     463{
     464    XEvent npEvent;
     465    initXEvent(&npEvent);
     466
     467    XFocusChangeEvent& event = npEvent.xfocus;
     468    event.type = 9; // FocusIn gets unset somewhere
     469    event.mode = NotifyNormal;
     470    event.detail = NotifyDetailNone;
     471
     472    dispatchNPEvent(npEvent);
     473}
     474
     475void PluginView::handleFocusOutEvent()
     476{
     477    XEvent npEvent;
     478    initXEvent(&npEvent);
     479
     480    XFocusChangeEvent& event = npEvent.xfocus;
     481    event.type = 10; // FocusOut gets unset somewhere
     482    event.mode = NotifyNormal;
     483    event.detail = NotifyDetailNone;
     484
     485    dispatchNPEvent(npEvent);
     486}
     487#endif
    200488
    201489void PluginView::setParent(ScrollView* parent)
     
    209497void PluginView::setNPWindowRect(const IntRect&)
    210498{
    211     setNPWindowIfNeeded();
     499    if (!m_isWindowed)
     500        setNPWindowIfNeeded();
    212501}
    213502
     
    217506        return;
    218507
    219     m_npWindow.x = m_windowRect.x();
    220     m_npWindow.y = m_windowRect.y();
    221     m_npWindow.width = m_windowRect.width();
    222     m_npWindow.height = m_windowRect.height();
    223 
    224     m_npWindow.clipRect.left = m_clipRect.x();
    225     m_npWindow.clipRect.top = m_clipRect.y();
    226     m_npWindow.clipRect.right = m_clipRect.width();
    227     m_npWindow.clipRect.bottom = m_clipRect.height();
    228 
    229     GtkAllocation allocation = { m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height() };
    230     gtk_widget_size_allocate(platformPluginWidget(), &allocation);
    231 #if defined(XP_UNIX)
    232     if (!m_needsXEmbed) {
    233         gtk_xtbin_set_position(GTK_XTBIN(platformPluginWidget()), m_windowRect.x(), m_windowRect.y());
    234         gtk_xtbin_resize(platformPluginWidget(), m_windowRect.width(), m_windowRect.height());
    235     }
    236 #endif
     508    // If the plugin didn't load sucessfully, no point in calling setwindow
     509    if (m_status != PluginStatusLoadedSuccessfully)
     510        return;
     511
     512    // On Unix, only call plugin's setwindow if it's full-page or windowed
     513    if (m_mode != NP_FULL && m_mode != NP_EMBED)
     514        return;
     515
     516    // Check if the platformPluginWidget still exists
     517    if (m_isWindowed && !platformPluginWidget())
     518        return;
     519
     520#if defined(XP_UNIX)
     521    if (!m_hasPendingGeometryChange)
     522        return;
     523    m_hasPendingGeometryChange = false;
     524#endif
     525
     526    if (m_isWindowed) {
     527        m_npWindow.x = m_windowRect.x();
     528        m_npWindow.y = m_windowRect.y();
     529        m_npWindow.width = m_windowRect.width();
     530        m_npWindow.height = m_windowRect.height();
     531
     532        m_npWindow.clipRect.left = m_clipRect.x();
     533        m_npWindow.clipRect.top = m_clipRect.y();
     534        m_npWindow.clipRect.right = m_clipRect.width();
     535        m_npWindow.clipRect.bottom = m_clipRect.height();
     536
     537        GtkAllocation allocation = { m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height() };
     538        gtk_widget_size_allocate(platformPluginWidget(), &allocation);
     539#if defined(XP_UNIX)
     540        if (!m_needsXEmbed) {
     541            gtk_xtbin_set_position(GTK_XTBIN(platformPluginWidget()), m_windowRect.x(), m_windowRect.y());
     542            gtk_xtbin_resize(platformPluginWidget(), m_windowRect.width(), m_windowRect.height());
     543        }
     544#endif
     545    } else {
     546        m_npWindow.x = 0;
     547        m_npWindow.y = 0;
     548
     549        m_npWindow.clipRect.left = 0;
     550        m_npWindow.clipRect.top = 0;
     551        m_npWindow.clipRect.right = 0;
     552        m_npWindow.clipRect.bottom = 0;
     553    }
     554
     555    // FLASH WORKAROUND: Only set initially. Multiple calls to
     556    // setNPWindow() cause the plugin to crash in windowed mode.
     557    if (!m_isWindowed || m_npWindow.width == (unsigned int)-1 || m_npWindow.height == (unsigned int)-1) {
     558        m_npWindow.width = m_windowRect.width();
     559        m_npWindow.height = m_windowRect.height();
     560    }
    237561
    238562    PluginView::setCurrentPluginView(this);
     
    311635    case NPNVjavascriptEnabledBool:
    312636        *static_cast<NPBool*>(value) = true;
     637        return NPERR_NO_ERROR;
     638
     639    case NPNVSupportsWindowless:
     640#if defined(XP_UNIX)
     641        *static_cast<NPBool*>(value) = true;
     642#else
     643        *static_cast<NPBool*>(value) = false;
     644#endif
    313645        return NPERR_NO_ERROR;
    314646
     
    416748
    417749    IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top);
    418     invalidateRect(r);
     750    invalidateWindowlessPluginRect(r);
    419751}
    420752
     
    433765}
    434766
     767static Display* getPluginDisplay()
     768{
     769    // The plugin toolkit might have a different X connection open.  Since we're
     770    // a gdk/gtk app, we'll (probably?) have the same X connection as any gdk-based
     771    // plugins, so we can return that.  We might want to add other implementations here
     772    // later.
     773
     774#if defined(XP_UNIX)
     775    return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
     776#else
     777    return 0;
     778#endif
     779}
     780
    435781static gboolean
    436 plug_removed_cb(GtkSocket *socket, gpointer)
     782plug_removed_cb(GtkSocket* socket, gpointer)
    437783{
    438784    return TRUE;
    439785}
     786
     787#if defined(XP_UNIX)
     788static void getVisualAndColormap(int depth, Visual** visual, Colormap* colormap)
     789{
     790    *visual = 0;
     791    *colormap = 0;
     792
     793    int rmaj, rmin;
     794    if (depth == 32 && (!XRenderQueryVersion(GDK_DISPLAY(), &rmaj, &rmin) || (rmaj == 0 && rmin < 5)))
     795        return;
     796
     797    XVisualInfo templ;
     798    templ.screen  = gdk_screen_get_number(gdk_screen_get_default());
     799    templ.depth   = depth;
     800    templ.c_class = TrueColor;
     801    int nVisuals;
     802    XVisualInfo* visualInfo = XGetVisualInfo(GDK_DISPLAY(), VisualScreenMask | VisualDepthMask | VisualClassMask, &templ, &nVisuals);
     803
     804    if (!nVisuals)
     805        return;
     806
     807    if (depth == 32) {
     808        for (int idx = 0; idx < nVisuals; ++idx) {
     809            XRenderPictFormat* format = XRenderFindVisualFormat(GDK_DISPLAY(), visualInfo[idx].visual);
     810            if (format->type == PictTypeDirect && format->direct.alphaMask) {
     811                 *visual = visualInfo[idx].visual;
     812                 break;
     813            }
     814         }
     815    } else
     816        *visual = visualInfo[0].visual;
     817
     818    XFree(visualInfo);
     819
     820    if (*visual)
     821        *colormap = XCreateColormap(GDK_DISPLAY(), GDK_ROOT_WINDOW(), *visual, AllocNone);
     822}
     823#endif
    440824
    441825bool PluginView::platformStart()
     
    453837    }
    454838
    455 #if defined(XP_UNIX)
    456     if (m_needsXEmbed) {
     839    if (m_isWindowed) {
     840#if defined(XP_UNIX)
     841        if (m_needsXEmbed) {
     842            setPlatformWidget(gtk_socket_new());
     843            gtk_container_add(GTK_CONTAINER(m_parentFrame->view()->hostWindow()->platformPageClient()), platformPluginWidget());
     844            g_signal_connect(platformPluginWidget(), "plug_removed", G_CALLBACK(plug_removed_cb), NULL);
     845        } else
     846            setPlatformWidget(gtk_xtbin_new(m_parentFrame->view()->hostWindow()->platformPageClient()->window, 0));
     847#else
    457848        setPlatformWidget(gtk_socket_new());
    458849        gtk_container_add(GTK_CONTAINER(m_parentFrame->view()->hostWindow()->platformPageClient()), platformPluginWidget());
    459         g_signal_connect(platformPluginWidget(), "plug_removed", G_CALLBACK(plug_removed_cb), NULL);
    460     } else if (m_isWindowed)
    461         setPlatformWidget(gtk_xtbin_new(m_parentFrame->view()->hostWindow()->platformPageClient()->window, 0));
    462 #else
    463     setPlatformWidget(gtk_socket_new());
    464     gtk_container_add(GTK_CONTAINER(m_parentFrame->view()->hostWindow()->platformPageClient()), platformPluginWidget());
    465 #endif
     850#endif
     851    } else {
     852        setPlatformWidget(0);
     853        m_pluginDisplay = getPluginDisplay();
     854    }
     855
    466856    show();
     857
     858#if defined(XP_UNIX)
     859        NPSetWindowCallbackStruct* ws = new NPSetWindowCallbackStruct();
     860        ws->type = 0;
     861#endif
    467862
    468863    if (m_isWindowed) {
    469864        m_npWindow.type = NPWindowTypeWindow;
    470865#if defined(XP_UNIX)
    471         NPSetWindowCallbackStruct *ws = new NPSetWindowCallbackStruct();
    472 
    473         ws->type = 0;
    474 
    475866        if (m_needsXEmbed) {
    476867            gtk_widget_realize(platformPluginWidget());
     
    488879        }
    489880        XFlush (ws->display);
    490 
    491         m_npWindow.ws_info = ws;
    492881#elif defined(GDK_WINDOWING_WIN32)
    493882        m_npWindow.window = (void*)GDK_WINDOW_HWND(platformPluginWidget()->window);
     
    495884    } else {
    496885        m_npWindow.type = NPWindowTypeDrawable;
    497         m_npWindow.window = 0;
    498     }
     886        m_npWindow.window = 0; // Not used?
     887
     888#if defined(XP_UNIX)
     889        GdkScreen* gscreen = gdk_screen_get_default();
     890        GdkVisual* gvisual = gdk_screen_get_system_visual(gscreen);
     891
     892        if (gvisual->depth == 32 || !m_plugin->quirks().contains(PluginQuirkRequiresDefaultScreenDepth)) {
     893            getVisualAndColormap(32, &m_visual, &m_colormap);
     894            ws->depth = 32;
     895        }
     896
     897        if (!m_visual) {
     898            getVisualAndColormap(gvisual->depth, &m_visual, &m_colormap);
     899            ws->depth = gvisual->depth;
     900        }
     901
     902        ws->display = GDK_DISPLAY();
     903        ws->visual = m_visual;
     904        ws->colormap = m_colormap;
     905
     906        m_npWindow.x = 0;
     907        m_npWindow.y = 0;
     908        m_npWindow.width = -1;
     909        m_npWindow.height = -1;
     910#else
     911        notImplemented();
     912        m_status = PluginStatusCanNotLoadPlugin;
     913        return false;
     914#endif
     915    }
     916
     917#if defined(XP_UNIX)
     918    m_npWindow.ws_info = ws;
     919#endif
    499920
    500921    // TODO remove in favor of null events, like mac port?
    501     if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall)))
     922    if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall))) {
    502923        updatePluginWidget(); // was: setNPWindowIfNeeded(), but this doesn't produce 0x0 rects at first go
     924        setNPWindowIfNeeded();
     925    }
    503926
    504927    return true;
     
    507930void PluginView::platformDestroy()
    508931{
     932#if defined(XP_UNIX)
     933    if (m_drawable) {
     934        XFreePixmap(GDK_DISPLAY(), m_drawable);
     935        m_drawable = 0;
     936    }
     937#endif
    509938}
    510939
Note: See TracChangeset for help on using the changeset viewer.