[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.19-706-ge5415e9

eric at webkit.org eric at webkit.org
Thu Feb 4 21:29:54 UTC 2010


The following commit has been merged in the webkit-1.1 branch:
commit 9399fcd0ae5a8e727bd703813e045ccea76038c5
Author: eric at webkit.org <eric at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Jan 27 23:16:04 2010 +0000

    2010-01-27  Brian Tarricone  <brian at 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):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@53955 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index fcb24b4..fd48756 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,43 @@
+2010-01-27  Brian Tarricone  <brian at 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):
+
 2010-01-27  Anton Muhin  <antonm at chromium.org>
 
         Reviewed by David Levin.
diff --git a/WebCore/plugins/PluginView.cpp b/WebCore/plugins/PluginView.cpp
index f669c6d..3ff4c82 100644
--- a/WebCore/plugins/PluginView.cpp
+++ b/WebCore/plugins/PluginView.cpp
@@ -152,7 +152,7 @@ void PluginView::handleEvent(Event* event)
         handleMouseEvent(static_cast<MouseEvent*>(event));
     else if (event->isKeyboardEvent())
         handleKeyboardEvent(static_cast<KeyboardEvent*>(event));
-#if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API)
+#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
     else if (event->type() == eventNames().DOMFocusOutEvent)
         handleFocusOutEvent();
     else if (event->type() == eventNames().DOMFocusInEvent)
@@ -804,7 +804,7 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p
     , m_isTransparent(false)
     , m_haveInitialized(false)
     , m_isWaitingToStart(false)
-#if defined(XP_UNIX) || defined(Q_WS_X11)
+#if defined(XP_UNIX)
     , m_needsXEmbed(false)
 #endif
 #if OS(WINDOWS) && ENABLE(NETSCAPE_PLUGIN_API)
@@ -823,7 +823,7 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p
     , m_contextRef(0)
     , m_fakeWindow(0)
 #endif
-#if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API)
+#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
     , m_hasPendingGeometryChange(true)
     , m_drawable(0)
     , m_visual(0)
diff --git a/WebCore/plugins/PluginView.h b/WebCore/plugins/PluginView.h
index dbbb94d..0dd5e0b 100644
--- a/WebCore/plugins/PluginView.h
+++ b/WebCore/plugins/PluginView.h
@@ -265,7 +265,7 @@ namespace WebCore {
 
         void handleKeyboardEvent(KeyboardEvent*);
         void handleMouseEvent(MouseEvent*);
-#if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API)
+#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
         void handleFocusInEvent();
         void handleFocusOutEvent();
 #endif
@@ -298,7 +298,7 @@ namespace WebCore {
         bool m_haveInitialized;
         bool m_isWaitingToStart;
 
-#if defined(XP_UNIX) || defined(Q_WS_X11)
+#if defined(XP_UNIX)
         bool m_needsXEmbed;
 #endif
 
@@ -326,7 +326,7 @@ public:
 
 private:
 
-#if defined(XP_UNIX) || defined(Q_WS_X11) || OS(SYMBIAN)
+#if defined(XP_UNIX) || PLATFORM(SYMBIAN)
         void setNPWindowIfNeeded();
 #elif defined(XP_MACOSX)
         NP_CGContext m_npCgContext;
@@ -342,7 +342,7 @@ private:
         Point globalMousePosForPlugin() const;
 #endif
 
-#if defined(Q_WS_X11) && ENABLE(NETSCAPE_PLUGIN_API)
+#if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API)
         bool m_hasPendingGeometryChange;
         Pixmap m_drawable;
         Visual* m_visual;
diff --git a/WebCore/plugins/gtk/PluginViewGtk.cpp b/WebCore/plugins/gtk/PluginViewGtk.cpp
index f1add65..c473c35 100644
--- a/WebCore/plugins/gtk/PluginViewGtk.cpp
+++ b/WebCore/plugins/gtk/PluginViewGtk.cpp
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
  * Copyright (C) 2008 Collabora Ltd. All rights reserved.
+ * Copyright (C) 2009, 2010 Kakai, Inc. <brian at kakai.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -44,6 +45,7 @@
 #include "KeyboardEvent.h"
 #include "MouseEvent.h"
 #include "Page.h"
+#include "PlatformKeyboardEvent.h"
 #include "PlatformMouseEvent.h"
 #include "PluginDebug.h"
 #include "PluginMainThreadScheduler.h"
@@ -62,6 +64,10 @@
 
 #if defined(XP_UNIX)
 #include "gtk2xtbin.h"
+#define Bool int // this got undefined somewhere
+#define Status int // ditto
+#include <X11/extensions/Xrender.h>
+#include <cairo/cairo-xlib.h>
 #include <gdk/gdkx.h>
 #elif defined(GDK_WINDOWING_WIN32)
 #include "PluginMessageThrottlerWin.h"
@@ -99,9 +105,18 @@ bool PluginView::dispatchNPEvent(NPEvent& event)
     return accepted;
 }
 
+#if defined(XP_UNIX)
+static Window getRootWindow(Frame* parentFrame)
+{
+    GtkWidget* parentWidget = parentFrame->view()->hostWindow()->platformPageClient();
+    GdkScreen* gscreen = gtk_widget_get_screen(parentWidget);
+    return GDK_WINDOW_XWINDOW(gdk_screen_get_root_window(gscreen));
+}
+#endif
+
 void PluginView::updatePluginWidget()
 {
-    if (!parent() || !m_isWindowed)
+    if (!parent())
         return;
 
     ASSERT(parent()->isFrameView());
@@ -116,6 +131,29 @@ void PluginView::updatePluginWidget()
 
     if (platformPluginWidget() && (m_windowRect != oldWindowRect || m_clipRect != oldClipRect))
         setNPWindowIfNeeded();
+
+#if defined(XP_UNIX)
+    if (!m_isWindowed && m_windowRect.size() != oldWindowRect.size()) {
+        if (m_drawable)
+            XFreePixmap(GDK_DISPLAY(), m_drawable);
+
+        m_drawable = XCreatePixmap(GDK_DISPLAY(), getRootWindow(m_parentFrame),
+                                   m_windowRect.width(), m_windowRect.height(),
+                                   ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth);
+        XSync(GDK_DISPLAY(), False); // make sure that the server knows about the Drawable
+    }
+
+    // do not call setNPWindowIfNeeded() immediately, will be called on paint()
+    m_hasPendingGeometryChange = true;
+#endif
+
+    // In order to move/resize the plugin window at the same time as the
+    // rest of frame during e.g. scrolling, we set the window geometry
+    // in the paint() function, but as paint() isn't called when the
+    // plugin window is outside the frame which can be caused by a
+    // scroll, we need to move/resize immediately.
+    if (!m_windowRect.intersects(frameView->frameRect()))
+        setNPWindowIfNeeded();
 }
 
 void PluginView::setFocus()
@@ -161,43 +199,293 @@ void PluginView::paint(GraphicsContext* context, const IntRect& rect)
     if (m_isWindowed)
         return;
 
-    NPEvent npEvent;
-    /* Need to synthesize Xevents here */
+#if defined(XP_UNIX)
+    if (!m_drawable)
+        return;
+
+    const bool syncX = m_pluginDisplay && m_pluginDisplay != GDK_DISPLAY();
+
+    IntRect exposedRect(rect);
+    exposedRect.intersect(frameRect());
+    exposedRect.move(-frameRect().x(), -frameRect().y());
+
+    Window dummyW;
+    int dummyI;
+    unsigned int dummyUI, actualDepth = 0;
+    XGetGeometry(GDK_DISPLAY(), m_drawable, &dummyW, &dummyI, &dummyI,
+                 &dummyUI, &dummyUI, &dummyUI, &actualDepth);
+
+    const int drawableDepth = ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth;
+    ASSERT(drawableDepth == actualDepth);
+
+    cairo_surface_t* drawableSurface = cairo_xlib_surface_create(GDK_DISPLAY(),
+                                                                 m_drawable,
+                                                                 m_visual,
+                                                                 m_windowRect.width(),
+                                                                 m_windowRect.height());
+
+    if (m_isTransparent && drawableDepth != 32) {
+        // Attempt to fake it when we don't have an alpha channel on our
+        // pixmap.  If that's not possible, at least clear the window to
+        // avoid drawing artifacts.
+        GtkWidget* widget = m_parentFrame->view()->hostWindow()->platformPageClient();
+        GdkDrawable* gdkBackingStore = 0;
+        gint xoff = 0, yoff = 0;
+
+        gdk_window_get_internal_paint_info(widget->window, &gdkBackingStore, &xoff, &yoff);
+
+        GC gc = XDefaultGC(GDK_DISPLAY(), gdk_screen_get_number(gdk_screen_get_default()));
+        if (gdkBackingStore) {
+            XCopyArea(GDK_DISPLAY(), GDK_DRAWABLE_XID(gdkBackingStore), m_drawable, gc,
+                      m_windowRect.x() + exposedRect.x() - xoff,
+                      m_windowRect.y() + exposedRect.y() - yoff,
+                      exposedRect.width(), exposedRect.height(),
+                      exposedRect.x(), exposedRect.y());
+        } else {
+            // no valid backing store; clear to the background color
+            XFillRectangle(GDK_DISPLAY(), m_drawable, gc,
+                           exposedRect.x(), exposedRect.y(),
+                           exposedRect.width(), exposedRect.height());
+        }
+    } else if (m_isTransparent) {
+        // If we have a 32 bit drawable and the plugin wants transparency,
+        // we'll clear the exposed area to transparent first.  Otherwise,
+        // we'd end up with junk in there from the last paint, or, worse,
+        // uninitialized data.
+        cairo_t* crFill = cairo_create(drawableSurface);
+
+        cairo_set_operator(crFill, CAIRO_OPERATOR_SOURCE);
+        cairo_pattern_t* fill = cairo_pattern_create_rgba(0., 0., 0., 0.);
+        cairo_set_source(crFill, fill);
+
+        cairo_rectangle(crFill, exposedRect.x(), exposedRect.y(),
+                        exposedRect.width(), exposedRect.height());
+        cairo_clip(crFill);
+        cairo_paint(crFill);
+
+        cairo_destroy(crFill);
+        cairo_pattern_destroy(fill);
+    }
 
-    m_npWindow.type = NPWindowTypeDrawable;
+    XEvent xevent;
+    memset(&xevent, 0, sizeof(XEvent));
+    XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose;
+    exposeEvent.type = GraphicsExpose;
+    exposeEvent.display = GDK_DISPLAY();
+    exposeEvent.drawable = m_drawable;
+    exposeEvent.x = exposedRect.x();
+    exposeEvent.y = exposedRect.y();
+    exposeEvent.width = exposedRect.x() + exposedRect.width(); // flash bug? it thinks width is the right in transparent mode
+    exposeEvent.height = exposedRect.y() + exposedRect.height(); // flash bug? it thinks height is the bottom in transparent mode
 
-    ASSERT(parent()->isFrameView());
+    dispatchNPEvent(xevent);
+
+    if (syncX)
+        XSync(m_pluginDisplay, False); // sync changes by plugin
 
-    if (!dispatchNPEvent(npEvent))
-        LOG(Events, "PluginView::paint(): Paint event not accepted");
+    cairo_t* cr = context->platformContext();
+    cairo_save(cr);
+
+    cairo_set_source_surface(cr, drawableSurface, frameRect().x(), frameRect().y());
+
+    cairo_rectangle(cr,
+                    frameRect().x() + exposedRect.x(), frameRect().y() + exposedRect.y(),
+                    exposedRect.width(), exposedRect.height());
+    cairo_clip(cr);
+
+    if (m_isTransparent)
+        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+    else
+        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+    cairo_paint(cr);
+
+    cairo_restore(cr);
+    cairo_surface_destroy(drawableSurface);
+#endif // defined(XP_UNIX)
 }
 
 void PluginView::handleKeyboardEvent(KeyboardEvent* event)
 {
-    NPEvent npEvent;
-    
-    /* FIXME: Synthesize an XEvent to pass through */
-
     JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
-    if (!dispatchNPEvent(npEvent))
+
+    if (m_isWindowed)
+        return;
+
+    if (event->type() != eventNames().keydownEvent && event->type() != eventNames().keyupEvent)
+        return;
+
+    NPEvent xEvent;
+#if defined(XP_UNIX)
+    GdkEventKey* gdkEvent = event->keyEvent()->gdkEventKey();
+
+    xEvent.type = (event->type() == eventNames().keydownEvent) ? 2 : 3; // KeyPress/Release get unset somewhere
+    xEvent.xkey.root = getRootWindow(m_parentFrame);
+    xEvent.xkey.subwindow = 0; // we have no child window
+    xEvent.xkey.time = event->timeStamp();
+    xEvent.xkey.state = gdkEvent->state; // GdkModifierType mirrors xlib state masks
+    xEvent.xkey.keycode = gdkEvent->hardware_keycode;
+    xEvent.xkey.same_screen = true;
+
+    // NOTE: As the XEvents sent to the plug-in are synthesized and there is not a native window
+    // corresponding to the plug-in rectangle, some of the members of the XEvent structures are not
+    // set to their normal Xserver values. e.g. Key events don't have a position.
+    // source: https://developer.mozilla.org/en/NPEvent
+    xEvent.xkey.x = 0;
+    xEvent.xkey.y = 0;
+    xEvent.xkey.x_root = 0;
+    xEvent.xkey.y_root = 0;
+#endif
+
+    if (!dispatchNPEvent(xEvent))
         event->setDefaultHandled();
 }
 
-void PluginView::handleMouseEvent(MouseEvent* event)
+#if defined(XP_UNIX)
+static unsigned int inputEventState(MouseEvent* event)
 {
-    NPEvent npEvent;
+    unsigned int state = 0;
+    if (event->ctrlKey())
+        state |= ControlMask;
+    if (event->shiftKey())
+        state |= ShiftMask;
+    if (event->altKey())
+        state |= Mod1Mask;
+    if (event->metaKey())
+        state |= Mod4Mask;
+    return state;
+}
 
-    if (!m_isWindowed)
-      return;
+void PluginView::initXEvent(XEvent* xEvent)
+{
+    memset(xEvent, 0, sizeof(XEvent));
+
+    xEvent->xany.serial = 0; // we are unaware of the last request processed by X Server
+    xEvent->xany.send_event = false;
+    xEvent->xany.display = GDK_DISPLAY();
+    // NOTE: event->xany.window doesn't always correspond to the .window property of other XEvent's
+    // but does in the case of KeyPress, KeyRelease, ButtonPress, ButtonRelease, and MotionNotify
+    // events; thus, this is right:
+    GtkWidget* widget = m_parentFrame->view()->hostWindow()->platformPageClient();
+    xEvent->xany.window = widget ? GDK_WINDOW_XWINDOW(widget->window) : 0;
+}
+
+static void setXButtonEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos, Frame* parentFrame)
+{
+    XButtonEvent& xbutton = xEvent->xbutton;
+    xbutton.type = event->type() == eventNames().mousedownEvent ? ButtonPress : ButtonRelease;
+    xbutton.root = getRootWindow(parentFrame);
+    xbutton.subwindow = 0;
+    xbutton.time = event->timeStamp();
+    xbutton.x = postZoomPos.x();
+    xbutton.y = postZoomPos.y();
+    xbutton.x_root = event->screenX();
+    xbutton.y_root = event->screenY();
+    xbutton.state = inputEventState(event);
+    switch (event->button()) {
+    case MiddleButton:
+        xbutton.button = Button2;
+        break;
+    case RightButton:
+        xbutton.button = Button3;
+        break;
+    case LeftButton:
+    default:
+        xbutton.button = Button1;
+        break;
+    }
+    xbutton.same_screen = true;
+}
+
+static void setXMotionEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos, Frame* parentFrame)
+{
+    XMotionEvent& xmotion = xEvent->xmotion;
+    xmotion.type = MotionNotify;
+    xmotion.root = getRootWindow(parentFrame);
+    xmotion.subwindow = 0;
+    xmotion.time = event->timeStamp();
+    xmotion.x = postZoomPos.x();
+    xmotion.y = postZoomPos.y();
+    xmotion.x_root = event->screenX();
+    xmotion.y_root = event->screenY();
+    xmotion.state = inputEventState(event);
+    xmotion.is_hint = NotifyNormal;
+    xmotion.same_screen = true;
+}
 
-    /* FIXME: Synthesize an XEvent to pass through */
-    IntPoint p = static_cast<FrameView*>(parent())->contentsToWindow(IntPoint(event->pageX(), event->pageY()));
+static void setXCrossingEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos, Frame* parentFrame)
+{
+    XCrossingEvent& xcrossing = xEvent->xcrossing;
+    xcrossing.type = event->type() == eventNames().mouseoverEvent ? EnterNotify : LeaveNotify;
+    xcrossing.root = getRootWindow(parentFrame);
+    xcrossing.subwindow = 0;
+    xcrossing.time = event->timeStamp();
+    xcrossing.x = postZoomPos.y();
+    xcrossing.y = postZoomPos.x();
+    xcrossing.x_root = event->screenX();
+    xcrossing.y_root = event->screenY();
+    xcrossing.state = inputEventState(event);
+    xcrossing.mode = NotifyNormal;
+    xcrossing.detail = NotifyDetailNone;
+    xcrossing.same_screen = true;
+    xcrossing.focus = false;
+}
+#endif
 
+void PluginView::handleMouseEvent(MouseEvent* event)
+{
     JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
-    if (!dispatchNPEvent(npEvent))
+
+    if (m_isWindowed)
+        return;
+
+    NPEvent xEvent;
+#if defined(XP_UNIX)
+    initXEvent(&xEvent);
+
+    IntPoint postZoomPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation()));
+
+    if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent)
+        setXButtonEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame);
+    else if (event->type() == eventNames().mousemoveEvent)
+        setXMotionEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame);
+    else if (event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mouseoverEvent)
+        setXCrossingEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame);
+    else
+        return;
+#endif
+
+    if (!dispatchNPEvent(xEvent))
         event->setDefaultHandled();
 }
 
+#if defined(XP_UNIX)
+void PluginView::handleFocusInEvent()
+{
+    XEvent npEvent;
+    initXEvent(&npEvent);
+
+    XFocusChangeEvent& event = npEvent.xfocus;
+    event.type = 9; // FocusIn gets unset somewhere
+    event.mode = NotifyNormal;
+    event.detail = NotifyDetailNone;
+
+    dispatchNPEvent(npEvent);
+}
+
+void PluginView::handleFocusOutEvent()
+{
+    XEvent npEvent;
+    initXEvent(&npEvent);
+
+    XFocusChangeEvent& event = npEvent.xfocus;
+    event.type = 10; // FocusOut gets unset somewhere
+    event.mode = NotifyNormal;
+    event.detail = NotifyDetailNone;
+
+    dispatchNPEvent(npEvent);
+}
+#endif
+
 void PluginView::setParent(ScrollView* parent)
 {
     Widget::setParent(parent);
@@ -208,7 +496,8 @@ void PluginView::setParent(ScrollView* parent)
 
 void PluginView::setNPWindowRect(const IntRect&)
 {
-    setNPWindowIfNeeded();
+    if (!m_isWindowed)
+        setNPWindowIfNeeded();
 }
 
 void PluginView::setNPWindowIfNeeded()
@@ -216,24 +505,59 @@ void PluginView::setNPWindowIfNeeded()
     if (!m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow)
         return;
 
-    m_npWindow.x = m_windowRect.x();
-    m_npWindow.y = m_windowRect.y();
-    m_npWindow.width = m_windowRect.width();
-    m_npWindow.height = m_windowRect.height();
+    // If the plugin didn't load sucessfully, no point in calling setwindow
+    if (m_status != PluginStatusLoadedSuccessfully)
+        return;
+
+    // On Unix, only call plugin's setwindow if it's full-page or windowed
+    if (m_mode != NP_FULL && m_mode != NP_EMBED)
+        return;
 
-    m_npWindow.clipRect.left = m_clipRect.x();
-    m_npWindow.clipRect.top = m_clipRect.y();
-    m_npWindow.clipRect.right = m_clipRect.width();
-    m_npWindow.clipRect.bottom = m_clipRect.height();
+    // Check if the platformPluginWidget still exists
+    if (m_isWindowed && !platformPluginWidget())
+        return;
 
-    GtkAllocation allocation = { m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height() };
-    gtk_widget_size_allocate(platformPluginWidget(), &allocation);
 #if defined(XP_UNIX)
-    if (!m_needsXEmbed) {
-        gtk_xtbin_set_position(GTK_XTBIN(platformPluginWidget()), m_windowRect.x(), m_windowRect.y());
-        gtk_xtbin_resize(platformPluginWidget(), m_windowRect.width(), m_windowRect.height());
-    }
+    if (!m_hasPendingGeometryChange)
+        return;
+    m_hasPendingGeometryChange = false;
+#endif
+
+    if (m_isWindowed) {
+        m_npWindow.x = m_windowRect.x();
+        m_npWindow.y = m_windowRect.y();
+        m_npWindow.width = m_windowRect.width();
+        m_npWindow.height = m_windowRect.height();
+
+        m_npWindow.clipRect.left = m_clipRect.x();
+        m_npWindow.clipRect.top = m_clipRect.y();
+        m_npWindow.clipRect.right = m_clipRect.width();
+        m_npWindow.clipRect.bottom = m_clipRect.height();
+
+        GtkAllocation allocation = { m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height() };
+        gtk_widget_size_allocate(platformPluginWidget(), &allocation);
+#if defined(XP_UNIX)
+        if (!m_needsXEmbed) {
+            gtk_xtbin_set_position(GTK_XTBIN(platformPluginWidget()), m_windowRect.x(), m_windowRect.y());
+            gtk_xtbin_resize(platformPluginWidget(), m_windowRect.width(), m_windowRect.height());
+        }
 #endif
+    } else {
+        m_npWindow.x = 0;
+        m_npWindow.y = 0;
+
+        m_npWindow.clipRect.left = 0;
+        m_npWindow.clipRect.top = 0;
+        m_npWindow.clipRect.right = 0;
+        m_npWindow.clipRect.bottom = 0;
+    }
+
+    // FLASH WORKAROUND: Only set initially. Multiple calls to
+    // setNPWindow() cause the plugin to crash in windowed mode.
+    if (!m_isWindowed || m_npWindow.width == (unsigned int)-1 || m_npWindow.height == (unsigned int)-1) {
+        m_npWindow.width = m_windowRect.width();
+        m_npWindow.height = m_windowRect.height();
+    }
 
     PluginView::setCurrentPluginView(this);
     JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
@@ -312,6 +636,14 @@ NPError PluginView::getValueStatic(NPNVariable variable, void* value)
         *static_cast<NPBool*>(value) = true;
         return NPERR_NO_ERROR;
 
+    case NPNVSupportsWindowless:
+#if defined(XP_UNIX)
+        *static_cast<NPBool*>(value) = true;
+#else
+        *static_cast<NPBool*>(value) = false;
+#endif
+        return NPERR_NO_ERROR;
+
     default:
         return NPERR_GENERIC_ERROR;
     }
@@ -415,7 +747,7 @@ void PluginView::invalidateRect(NPRect* rect)
     }
 
     IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top);
-    invalidateRect(r);
+    invalidateWindowlessPluginRect(r);
 }
 
 void PluginView::invalidateRegion(NPRegion)
@@ -432,12 +764,64 @@ void PluginView::forceRedraw()
         gtk_widget_queue_draw(m_parentFrame->view()->hostWindow()->platformPageClient());
 }
 
+static Display* getPluginDisplay()
+{
+    // The plugin toolkit might have a different X connection open.  Since we're
+    // a gdk/gtk app, we'll (probably?) have the same X connection as any gdk-based
+    // plugins, so we can return that.  We might want to add other implementations here
+    // later.
+
+#if defined(XP_UNIX)
+    return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+#else
+    return 0;
+#endif
+}
+
 static gboolean
-plug_removed_cb(GtkSocket *socket, gpointer)
+plug_removed_cb(GtkSocket* socket, gpointer)
 {
     return TRUE;
 }
 
+#if defined(XP_UNIX)
+static void getVisualAndColormap(int depth, Visual** visual, Colormap* colormap)
+{
+    *visual = 0;
+    *colormap = 0;
+
+    int rmaj, rmin;
+    if (depth == 32 && (!XRenderQueryVersion(GDK_DISPLAY(), &rmaj, &rmin) || (rmaj == 0 && rmin < 5)))
+        return;
+
+    XVisualInfo templ;
+    templ.screen  = gdk_screen_get_number(gdk_screen_get_default());
+    templ.depth   = depth;
+    templ.c_class = TrueColor;
+    int nVisuals;
+    XVisualInfo* visualInfo = XGetVisualInfo(GDK_DISPLAY(), VisualScreenMask | VisualDepthMask | VisualClassMask, &templ, &nVisuals);
+
+    if (!nVisuals)
+        return;
+
+    if (depth == 32) {
+        for (int idx = 0; idx < nVisuals; ++idx) {
+            XRenderPictFormat* format = XRenderFindVisualFormat(GDK_DISPLAY(), visualInfo[idx].visual);
+            if (format->type == PictTypeDirect && format->direct.alphaMask) {
+                 *visual = visualInfo[idx].visual;
+                 break;
+            }
+         }
+    } else
+        *visual = visualInfo[0].visual;
+
+    XFree(visualInfo);
+
+    if (*visual)
+        *colormap = XCreateColormap(GDK_DISPLAY(), GDK_ROOT_WINDOW(), *visual, AllocNone);
+}
+#endif
+
 bool PluginView::platformStart()
 {
     ASSERT(m_isStarted);
@@ -452,26 +836,33 @@ bool PluginView::platformStart()
         PluginView::setCurrentPluginView(0);
     }
 
+    if (m_isWindowed) {
 #if defined(XP_UNIX)
-    if (m_needsXEmbed) {
+        if (m_needsXEmbed) {
+            setPlatformWidget(gtk_socket_new());
+            gtk_container_add(GTK_CONTAINER(m_parentFrame->view()->hostWindow()->platformPageClient()), platformPluginWidget());
+            g_signal_connect(platformPluginWidget(), "plug_removed", G_CALLBACK(plug_removed_cb), NULL);
+        } else
+            setPlatformWidget(gtk_xtbin_new(m_parentFrame->view()->hostWindow()->platformPageClient()->window, 0));
+#else
         setPlatformWidget(gtk_socket_new());
         gtk_container_add(GTK_CONTAINER(m_parentFrame->view()->hostWindow()->platformPageClient()), platformPluginWidget());
-        g_signal_connect(platformPluginWidget(), "plug_removed", G_CALLBACK(plug_removed_cb), NULL);
-    } else if (m_isWindowed)
-        setPlatformWidget(gtk_xtbin_new(m_parentFrame->view()->hostWindow()->platformPageClient()->window, 0));
-#else
-    setPlatformWidget(gtk_socket_new());
-    gtk_container_add(GTK_CONTAINER(m_parentFrame->view()->hostWindow()->platformPageClient()), platformPluginWidget());
 #endif
+    } else {
+        setPlatformWidget(0);
+        m_pluginDisplay = getPluginDisplay();
+    }
+
     show();
 
-    if (m_isWindowed) {
-        m_npWindow.type = NPWindowTypeWindow;
 #if defined(XP_UNIX)
-        NPSetWindowCallbackStruct *ws = new NPSetWindowCallbackStruct();
-
+        NPSetWindowCallbackStruct* ws = new NPSetWindowCallbackStruct();
         ws->type = 0;
+#endif
 
+    if (m_isWindowed) {
+        m_npWindow.type = NPWindowTypeWindow;
+#if defined(XP_UNIX)
         if (m_needsXEmbed) {
             gtk_widget_realize(platformPluginWidget());
             m_npWindow.window = (void*)gtk_socket_get_id(GTK_SOCKET(platformPluginWidget()));
@@ -487,25 +878,63 @@ bool PluginView::platformStart()
             ws->colormap = GTK_XTBIN(platformPluginWidget())->xtclient.xtcolormap;
         }
         XFlush (ws->display);
-
-        m_npWindow.ws_info = ws;
 #elif defined(GDK_WINDOWING_WIN32)
         m_npWindow.window = (void*)GDK_WINDOW_HWND(platformPluginWidget()->window);
 #endif
     } else {
         m_npWindow.type = NPWindowTypeDrawable;
-        m_npWindow.window = 0;
+        m_npWindow.window = 0; // Not used?
+
+#if defined(XP_UNIX)
+        GdkScreen* gscreen = gdk_screen_get_default();
+        GdkVisual* gvisual = gdk_screen_get_system_visual(gscreen);
+
+        if (gvisual->depth == 32 || !m_plugin->quirks().contains(PluginQuirkRequiresDefaultScreenDepth)) {
+            getVisualAndColormap(32, &m_visual, &m_colormap);
+            ws->depth = 32;
+        }
+
+        if (!m_visual) {
+            getVisualAndColormap(gvisual->depth, &m_visual, &m_colormap);
+            ws->depth = gvisual->depth;
+        }
+
+        ws->display = GDK_DISPLAY();
+        ws->visual = m_visual;
+        ws->colormap = m_colormap;
+
+        m_npWindow.x = 0;
+        m_npWindow.y = 0;
+        m_npWindow.width = -1;
+        m_npWindow.height = -1;
+#else
+        notImplemented();
+        m_status = PluginStatusCanNotLoadPlugin;
+        return false;
+#endif
     }
 
+#if defined(XP_UNIX)
+    m_npWindow.ws_info = ws;
+#endif
+
     // TODO remove in favor of null events, like mac port?
-    if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall)))
+    if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall))) {
         updatePluginWidget(); // was: setNPWindowIfNeeded(), but this doesn't produce 0x0 rects at first go
+        setNPWindowIfNeeded();
+    }
 
     return true;
 }
 
 void PluginView::platformDestroy()
 {
+#if defined(XP_UNIX)
+    if (m_drawable) {
+        XFreePixmap(GDK_DISPLAY(), m_drawable);
+        m_drawable = 0;
+    }
+#endif
 }
 
 void PluginView::halt()

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list