[EFL][GTK] Share plugin's implementation between EFL and Gtk ports.
authorryuan.choi@samsung.com <ryuan.choi@samsung.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Feb 2014 02:30:04 +0000 (02:30 +0000)
committerryuan.choi@samsung.com <ryuan.choi@samsung.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Feb 2014 02:30:04 +0000 (02:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=70592

Reviewed by Gyuyoung Kim.

Merge common logics of PluginViewGtk.cpp and PluginViewEfl.cpp to PluginViewX11.cpp.
So, this patch improves the windowless plugin support for the EFL port.

* GNUmakefile.am: Add include path for gtk2xtbin.h header file.
* GNUmakefile.list.am: Added PluginViewX11.cpp into source lists.
* PlatformEfl.cmake: Ditto.
* PlatformGTK.cmake: Ditto.
* plugins/PluginView.h: Added getRootWindow and getPluginDisply which implement platform specific code.
* plugins/efl/PluginViewEfl.cpp:
(WebCore::PluginView::getRootWindow):
(WebCore::PluginView::platformGetValueStatic): Turn on NPNVSupportsWindowless support.
(WebCore::PluginView::getPluginDisplay):
(WebCore::PluginView::platformStart):
* plugins/gtk/PluginViewGtk.cpp:
(WebCore::PluginView::getRootWindow):
(WebCore::setXButtonEventSpecificFields):
(WebCore::setXMotionEventSpecificFields):
(WebCore::setXCrossingEventSpecificFields):
(WebCore::PluginView::getPluginDisplay):
(WebCore::PluginView::platformStart):
* plugins/x11/PluginViewX11.cpp: Moved common logics from PluginViewGtk.cpp
(WebCore::PluginView::dispatchNPEvent):
(WebCore::PluginView::updatePluginWidget):
(WebCore::PluginView::handleFocusInEvent):
(WebCore::PluginView::invalidateRect):
(WebCore::PluginView::invalidateRegion):
(WebCore::PluginView::handleFocusOutEvent):
(WebCore::PluginView::initXEvent):
(WebCore::PluginView::paint):
(WebCore::PluginView::setParent):
(WebCore::PluginView::setNPWindowRect):
(WebCore::PluginView::setNPWindowIfNeeded):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@163505 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.am
Source/WebCore/GNUmakefile.list.am
Source/WebCore/PlatformEfl.cmake
Source/WebCore/PlatformGTK.cmake
Source/WebCore/plugins/PluginView.h
Source/WebCore/plugins/efl/PluginViewEfl.cpp
Source/WebCore/plugins/gtk/PluginViewGtk.cpp
Source/WebCore/plugins/x11/PluginViewX11.cpp [new file with mode: 0644]

index 3b5ee93..34c0b1c 100644 (file)
@@ -1,3 +1,43 @@
+2014-02-05  Ryuan Choi  <ryuan.choi@samsung.com>
+
+        [EFL][GTK] Share plugin's implementation between EFL and Gtk ports.
+        https://bugs.webkit.org/show_bug.cgi?id=70592
+
+        Reviewed by Gyuyoung Kim.
+
+        Merge common logics of PluginViewGtk.cpp and PluginViewEfl.cpp to PluginViewX11.cpp.
+        So, this patch improves the windowless plugin support for the EFL port.
+
+        * GNUmakefile.am: Add include path for gtk2xtbin.h header file.
+        * GNUmakefile.list.am: Added PluginViewX11.cpp into source lists.
+        * PlatformEfl.cmake: Ditto.
+        * PlatformGTK.cmake: Ditto.
+        * plugins/PluginView.h: Added getRootWindow and getPluginDisply which implement platform specific code.
+        * plugins/efl/PluginViewEfl.cpp:
+        (WebCore::PluginView::getRootWindow):
+        (WebCore::PluginView::platformGetValueStatic): Turn on NPNVSupportsWindowless support.
+        (WebCore::PluginView::getPluginDisplay):
+        (WebCore::PluginView::platformStart):
+        * plugins/gtk/PluginViewGtk.cpp:
+        (WebCore::PluginView::getRootWindow):
+        (WebCore::setXButtonEventSpecificFields):
+        (WebCore::setXMotionEventSpecificFields):
+        (WebCore::setXCrossingEventSpecificFields):
+        (WebCore::PluginView::getPluginDisplay):
+        (WebCore::PluginView::platformStart):
+        * plugins/x11/PluginViewX11.cpp: Moved common logics from PluginViewGtk.cpp
+        (WebCore::PluginView::dispatchNPEvent):
+        (WebCore::PluginView::updatePluginWidget):
+        (WebCore::PluginView::handleFocusInEvent):
+        (WebCore::PluginView::invalidateRect):
+        (WebCore::PluginView::invalidateRegion):
+        (WebCore::PluginView::handleFocusOutEvent):
+        (WebCore::PluginView::initXEvent):
+        (WebCore::PluginView::paint):
+        (WebCore::PluginView::setParent):
+        (WebCore::PluginView::setNPWindowRect):
+        (WebCore::PluginView::setNPWindowIfNeeded):
+
 2014-02-05  Anders Carlsson  <andersca@apple.com>
 
         Fix a warning.
index b10d2b2..6e48954 100644 (file)
@@ -93,6 +93,7 @@ webcore_cppflags += \
        -I$(srcdir)/Source/WebCore/platform/text/icu \
        -I$(srcdir)/Source/WebCore/platform/win \
        -I$(srcdir)/Source/WebCore/plugins \
+       -I$(srcdir)/Source/WebCore/plugins/gtk \
        -I$(srcdir)/Source/WebCore/plugins/win \
        -I$(srcdir)/Source/WebCore/rendering \
        -I$(srcdir)/Source/WebCore/rendering/line \
index 5e5f2f7..5dbea82 100644 (file)
@@ -6222,7 +6222,8 @@ webcoregtk_sources += \
        Source/WebCore/plugins/gtk/gtk2xtbin.h \
        Source/WebCore/plugins/gtk/PluginPackageGtk.cpp \
        Source/WebCore/plugins/gtk/PluginViewGtk.cpp \
-       Source/WebCore/plugins/gtk/xembed.h
+       Source/WebCore/plugins/gtk/xembed.h \
+       Source/WebCore/plugins/x11/PluginViewX11.cpp
 platformgtk_sources += \
        Source/WebCore/platform/gtk/WidgetBackingStoreGtkX11.h \
        Source/WebCore/platform/gtk/WidgetBackingStoreGtkX11.cpp
index 61fbff2..e7b7c98 100644 (file)
@@ -191,6 +191,8 @@ if (ENABLE_NETSCAPE_PLUGIN_API)
     list(APPEND WebCore_SOURCES
         plugins/efl/PluginPackageEfl.cpp
         plugins/efl/PluginViewEfl.cpp
+
+        plugins/x11/PluginViewX11.cpp
     )
 endif ()
 
index b58ee7f..6bdbf87 100644 (file)
@@ -282,6 +282,8 @@ if (ENABLE_NETSCAPE_PLUGIN_API)
         plugins/gtk/PluginPackageGtk.cpp
         plugins/gtk/PluginViewGtk.cpp
         plugins/gtk/gtk2xtbin.c
+
+        plugins/x11/PluginViewX11.cpp
     )
 else ()
     list(APPEND WebCore_SOURCES
index 5fd38d2..074a350 100644 (file)
@@ -57,6 +57,11 @@ typedef PlatformWidget PlatformPluginWidget;
 typedef struct _GtkSocket GtkSocket;
 #endif
 
+#if PLATFORM(X11)
+typedef unsigned long Window;
+typedef struct _XDisplay Display;
+#endif
+
 namespace JSC {
     namespace Bindings {
         class Instance;
@@ -65,6 +70,7 @@ namespace JSC {
 
 namespace WebCore {
     class Frame;
+    class FrameView;
     class Image;
     class HTMLPlugInElement;
     class KeyboardEvent;
@@ -234,6 +240,11 @@ namespace WebCore {
 #endif
         void keepAlive();
 
+#if PLATFORM(X11)
+        static Display* getPluginDisplay(Frame*);
+        static Window getRootWindow(Frame* parentFrame);
+#endif
+
     private:
         PluginView(Frame* parentFrame, const IntSize&, PluginPackage*, HTMLPlugInElement*, const URL&, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually);
 
index db8e687..7a0f598 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) 2008 Collabora Ltd. All rights reserved.
  * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
  * Copyright (C) 2009-2010 ProFUSION embedded systems
- * Copyright (C) 2009-2011 Samsung Electronics
+ * Copyright (C) 2009-2014 Samsung Electronics
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #include "Frame.h"
 #include "FrameView.h"
-#include "GraphicsContext.h"
 #include "HTMLNames.h"
 #include "HTMLPlugInElement.h"
-#include "HostWindow.h"
-#include "JSDOMWindowBase.h"
 #include "MouseEvent.h"
 #include "NotImplemented.h"
 #include "PluginPackage.h"
@@ -52,33 +49,12 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-bool PluginView::dispatchNPEvent(NPEvent& event)
+Window PluginView::getRootWindow(Frame* parentFrame)
 {
-    if (!m_plugin->pluginFuncs()->event)
-        return false;
-
-    PluginView::setCurrentPluginView(this);
-    JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonVM());
-    setCallingPlugin(true);
-
-    bool accepted = m_plugin->pluginFuncs()->event(m_instance, &event);
-
-    setCallingPlugin(false);
-    PluginView::setCurrentPluginView(0);
-    return accepted;
-}
-
-#if defined(XP_UNIX)
-void PluginView::handleFocusInEvent()
-{
-    notImplemented();
-}
-
-void PluginView::handleFocusOutEvent()
-{
-    notImplemented();
+    Evas* evas = evas_object_evas_get(parentFrame->view()->evasObject());
+    Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(evas);
+    return static_cast<Window>(ecore_evas_window_get(ecoreEvas));
 }
-#endif
 
 void PluginView::handleKeyboardEvent(KeyboardEvent*)
 {
@@ -117,11 +93,6 @@ void PluginView::handleMouseEvent(MouseEvent* event)
         event->setDefaultHandled();
 }
 
-void PluginView::updatePluginWidget()
-{
-    notImplemented();
-}
-
 void PluginView::setFocus(bool focused)
 {
     if (focused)
@@ -144,29 +115,6 @@ void PluginView::hide()
     Widget::hide();
 }
 
-void PluginView::paint(GraphicsContext* context, const IntRect& rect)
-{
-    if (!m_isStarted)
-        paintMissingPluginIcon(context, rect);
-}
-
-void PluginView::setParent(ScrollView* parent)
-{
-    Widget::setParent(parent);
-
-    if (parent)
-        init();
-}
-
-void PluginView::setNPWindowRect(const IntRect&)
-{
-    notImplemented();
-}
-
-void PluginView::setNPWindowIfNeeded()
-{
-}
-
 void PluginView::setParentVisible(bool visible)
 {
     Widget::setParentVisible(visible);
@@ -221,7 +169,7 @@ bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPErr
         return true;
 
     case NPNVSupportsWindowless:
-        *static_cast<NPBool*>(value) = false;
+        *static_cast<NPBool*>(value) = true;
         *result = NPERR_NO_ERROR;
         return true;
 
@@ -312,19 +260,9 @@ void PluginView::invalidateRect(const IntRect& rect)
     invalidateWindowlessPluginRect(rect);
 }
 
-void PluginView::invalidateRect(NPRect* rect)
-{
-    if (!rect) {
-        invalidate();
-        return;
-    }
-
-    invalidateRect(IntRect(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top));
-}
-
-void PluginView::invalidateRegion(NPRegion)
+Display* PluginView::getPluginDisplay(Frame*)
 {
-    notImplemented();
+    return static_cast<Display*>(ecore_x_display_get());
 }
 
 void PluginView::forceRedraw()
@@ -337,7 +275,41 @@ bool PluginView::platformStart()
     ASSERT(m_isStarted);
     ASSERT(m_status == PluginStatusLoadedSuccessfully);
 
-    notImplemented();
+    if (m_plugin->pluginFuncs()->getvalue) {
+        PluginView::setCurrentPluginView(this);
+        JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonVM());
+        setCallingPlugin(true);
+        m_plugin->pluginFuncs()->getvalue(m_instance, NPPVpluginNeedsXEmbed, &m_needsXEmbed);
+        setCallingPlugin(false);
+        PluginView::setCurrentPluginView(0);
+    }
+
+    setPlatformWidget(0);
+    m_pluginDisplay = getPluginDisplay(nullptr);
+
+    show();
+
+    NPSetWindowCallbackStruct* ws = new NPSetWindowCallbackStruct();
+    ws->type = 0;
+
+    m_npWindow.type = NPWindowTypeDrawable;
+    m_npWindow.window = 0; // Not used?
+
+    Screen* screen = static_cast<Screen*>(ecore_x_default_screen_get());
+    m_visual = static_cast<Visual*>(ecore_x_default_visual_get(m_pluginDisplay, screen));
+    m_colormap = ecore_x_default_colormap_get(m_pluginDisplay, screen);
+
+    ws->depth = ecore_x_default_depth_get(m_pluginDisplay, screen);
+    ws->display = m_pluginDisplay;
+    ws->visual = m_visual;
+    ws->colormap = m_colormap;
+
+    m_npWindow.ws_info = ws;
+
+    // FIXME: remove in favor of null events, like mac port?
+    if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall)))
+        updatePluginWidget(); // was: setNPWindowIfNeeded(), but this doesn't produce 0x0 rects at first go
+
     return true;
 }
 
index 0bbbee3..7a16f21 100644 (file)
@@ -52,7 +52,6 @@
 #include "MouseEvent.h"
 #include "NotImplemented.h"
 #include "Page.h"
-#include "PlatformContextCairo.h"
 #include "PlatformKeyboardEvent.h"
 #include "PlatformMouseEvent.h"
 #include "PluginDebug.h"
 #define String XtStringType
 #include "RefPtrCairo.h"
 #include "gtk2xtbin.h"
-#define Bool int // this got undefined somewhere
+#define Bool int // this became undefined in npruntime_internal.h
 #define Status int // ditto
 #include <X11/extensions/Xrender.h>
-#include <cairo-xlib.h>
 #include <gdk/gdkx.h>
 
 using JSC::ExecState;
@@ -93,65 +91,13 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-bool PluginView::dispatchNPEvent(NPEvent& event)
-{
-    // sanity check
-    if (!m_plugin->pluginFuncs()->event)
-        return false;
-
-    PluginView::setCurrentPluginView(this);
-    JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonVM());
-    setCallingPlugin(true);
-
-    bool accepted = !m_plugin->pluginFuncs()->event(m_instance, &event);
-
-    setCallingPlugin(false);
-    PluginView::setCurrentPluginView(0);
-    return accepted;
-}
-
-static Window getRootWindow(Frame* parentFrame)
+Window PluginView::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));
 }
 
-void PluginView::updatePluginWidget()
-{
-    if (!parent())
-        return;
-
-    ASSERT(parent()->isFrameView());
-    FrameView* frameView = toFrameView(parent());
-
-    IntRect oldWindowRect = m_windowRect;
-    IntRect oldClipRect = m_clipRect;
-
-    m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
-    m_clipRect = windowClipRect();
-    m_clipRect.move(-m_windowRect.x(), -m_windowRect.y());
-
-    if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect)
-        return;
-
-    if (m_status != PluginStatusLoadedSuccessfully)
-        return;
-
-    if (!m_isWindowed && !m_windowRect.isEmpty()) {
-        Display* display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
-        if (m_drawable)
-            XFreePixmap(display, m_drawable);
-            
-        m_drawable = XCreatePixmap(display, getRootWindow(m_parentFrame.get()),
-                                   m_windowRect.width(), m_windowRect.height(),
-                                   ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth);
-        XSync(display, false); // make sure that the server knows about the Drawable
-    }
-
-    setNPWindowIfNeeded();
-}
-
 void PluginView::setFocus(bool focused)
 {
     ASSERT(platformPluginWidget() == platformWidget());
@@ -172,96 +118,6 @@ void PluginView::hide()
     Widget::hide();
 }
 
-void PluginView::paint(GraphicsContext* context, const IntRect& rect)
-{
-    if (!m_isStarted || m_status != PluginStatusLoadedSuccessfully) {
-        paintMissingPluginIcon(context, rect);
-        return;
-    }
-
-    if (context->paintingDisabled())
-        return;
-
-    setNPWindowIfNeeded();
-
-    if (m_isWindowed)
-        return;
-
-    if (!m_drawable)
-        return;
-
-    Display* display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
-    const bool syncX = m_pluginDisplay && m_pluginDisplay != display;
-
-    IntRect exposedRect(rect);
-    exposedRect.intersect(frameRect());
-    exposedRect.move(-frameRect().x(), -frameRect().y());
-
-    RefPtr<cairo_surface_t> drawableSurface = adoptRef(cairo_xlib_surface_create(display,
-                                                       m_drawable,
-                                                       m_visual,
-                                                       m_windowRect.width(),
-                                                       m_windowRect.height()));
-
-    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.
-        RefPtr<cairo_t> cr = adoptRef(cairo_create(drawableSurface.get()));
-
-        if (!(cairo_surface_get_content(drawableSurface.get()) & CAIRO_CONTENT_ALPHA)) {
-            // 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.
-
-            // This Would not work without double buffering, but we always use it.
-            cairo_set_source_surface(cr.get(), cairo_get_group_target(context->platformContext()->cr()),
-                                     -m_windowRect.x(), -m_windowRect.y());
-            cairo_set_operator(cr.get(), CAIRO_OPERATOR_SOURCE);
-        } else
-            cairo_set_operator(cr.get(), CAIRO_OPERATOR_CLEAR);
-
-        cairo_rectangle(cr.get(), exposedRect.x(), exposedRect.y(),
-                        exposedRect.width(), exposedRect.height());
-        cairo_fill(cr.get());
-    }
-
-    XEvent xevent;
-    memset(&xevent, 0, sizeof(XEvent));
-    XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose;
-    exposeEvent.type = GraphicsExpose;
-    exposeEvent.display = 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
-
-    dispatchNPEvent(xevent);
-
-    if (syncX)
-        XSync(m_pluginDisplay, false); // sync changes by plugin
-
-    cairo_t* cr = context->platformContext()->cr();
-    cairo_save(cr);
-
-    cairo_set_source_surface(cr, drawableSurface.get(), 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);
-}
-
 void PluginView::handleKeyboardEvent(KeyboardEvent* event)
 {
     JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonVM());
@@ -311,27 +167,11 @@ static unsigned int inputEventState(MouseEvent* event)
     return state;
 }
 
-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;
-    GtkWidget* widget = m_parentFrame->view()->hostWindow()->platformPageClient();
-    xEvent->xany.display = GDK_DISPLAY_XDISPLAY(gtk_widget_get_display(widget));
-
-    // Mozilla also sends None here for windowless plugins. See nsObjectFrame.cpp in the Mozilla sources.
-    // This method also sets up FocusIn and FocusOut events for windows plugins, but Mozilla doesn't
-    // even send these types of events to windowed plugins. In the future, it may be good to only
-    // send them to windowless plugins.
-    xEvent->xany.window = None;
-}
-
 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.root = PluginView::getRootWindow(parentFrame);
     xbutton.subwindow = 0;
     xbutton.time = event->timeStamp();
     xbutton.x = postZoomPos.x();
@@ -358,7 +198,7 @@ static void setXMotionEventSpecificFields(XEvent* xEvent, MouseEvent* event, con
 {
     XMotionEvent& xmotion = xEvent->xmotion;
     xmotion.type = MotionNotify;
-    xmotion.root = getRootWindow(parentFrame);
+    xmotion.root = PluginView::getRootWindow(parentFrame);
     xmotion.subwindow = 0;
     xmotion.time = event->timeStamp();
     xmotion.x = postZoomPos.x();
@@ -374,7 +214,7 @@ static void setXCrossingEventSpecificFields(XEvent* xEvent, MouseEvent* event, c
 {
     XCrossingEvent& xcrossing = xEvent->xcrossing;
     xcrossing.type = event->type() == eventNames().mouseoverEvent ? EnterNotify : LeaveNotify;
-    xcrossing.root = getRootWindow(parentFrame);
+    xcrossing.root = PluginView::getRootWindow(parentFrame);
     xcrossing.subwindow = 0;
     xcrossing.time = event->timeStamp();
     xcrossing.x = postZoomPos.y();
@@ -428,113 +268,6 @@ void PluginView::handleMouseEvent(MouseEvent* event)
         event->setDefaultHandled();
 }
 
-void PluginView::handleFocusInEvent()
-{
-    if (!m_isStarted || m_status != PluginStatusLoadedSuccessfully)
-        return;
-
-    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()
-{
-    if (!m_isStarted || m_status != PluginStatusLoadedSuccessfully)
-        return;
-
-    XEvent npEvent;
-    initXEvent(&npEvent);
-
-    XFocusChangeEvent& event = npEvent.xfocus;
-    event.type = 10; // FocusOut gets unset somewhere
-    event.mode = NotifyNormal;
-    event.detail = NotifyDetailNone;
-
-    dispatchNPEvent(npEvent);
-}
-
-void PluginView::setParent(ScrollView* parent)
-{
-    Widget::setParent(parent);
-
-    if (parent)
-        init();
-}
-
-void PluginView::setNPWindowRect(const IntRect&)
-{
-    if (!m_isWindowed)
-        setNPWindowIfNeeded();
-}
-
-void PluginView::setNPWindowIfNeeded()
-{
-    if (!m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow)
-        return;
-
-    // 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;
-
-    // Check if the platformPluginWidget still exists
-    if (m_isWindowed && !platformPluginWidget())
-        return;
-
-    if (m_clipRect.isEmpty()) {
-        // If width or height are null, set the clipRect to null,
-        // indicating that the plugin is not visible/scrolled out.
-        m_npWindow.clipRect.left = 0;
-        m_npWindow.clipRect.right = 0;
-        m_npWindow.clipRect.top = 0;
-        m_npWindow.clipRect.bottom = 0;
-    } else {
-        // Clipping rectangle of the plug-in; the origin is the top left corner of the drawable or window. 
-        m_npWindow.clipRect.left = m_npWindow.x + m_clipRect.x();
-        m_npWindow.clipRect.top = m_npWindow.y + m_clipRect.y();
-        m_npWindow.clipRect.right = m_npWindow.x + m_clipRect.x() + m_clipRect.width();
-        m_npWindow.clipRect.bottom = m_npWindow.y + m_clipRect.y() + m_clipRect.height();
-    }
-
-    // FLASH WORKAROUND: Only set initially. Multiple calls to
-    // setNPWindow() cause the plugin to crash in windowed mode.
-    if (!m_plugin->quirks().contains(PluginQuirkDontCallSetWindowMoreThanOnce) || !m_isWindowed
-        || m_npWindow.width == static_cast<uint32_t>(-1) || m_npWindow.height == static_cast<uint32_t>(-1)) {
-        m_npWindow.width = m_windowRect.width();
-        m_npWindow.height = m_windowRect.height();
-    }
-
-    PluginView::setCurrentPluginView(this);
-    JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonVM());
-    setCallingPlugin(true);
-    m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
-    setCallingPlugin(false);
-    PluginView::setCurrentPluginView(0);
-
-    if (!m_isWindowed)
-        return;
-
-    // GtkXtBin will call gtk_widget_size_allocate, so we don't need to do it here.
-    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());
-        return;
-    }
-
-    m_delayedAllocation = m_windowRect;
-    updateWidgetAllocationAndClip();
-}
-
 void PluginView::updateWidgetAllocationAndClip()
 {
     // If the window has not been embedded yet (the plug added), we delay setting its allocation until 
@@ -696,23 +429,6 @@ void PluginView::invalidateRect(const IntRect& rect)
     invalidateWindowlessPluginRect(rect);
 }
 
-void PluginView::invalidateRect(NPRect* rect)
-{
-    if (!rect) {
-        invalidate();
-        return;
-    }
-
-    IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top);
-    invalidateWindowlessPluginRect(r);
-}
-
-void PluginView::invalidateRegion(NPRegion)
-{
-    // TODO: optimize
-    invalidate();
-}
-
 void PluginView::forceRedraw()
 {
     if (m_isWindowed)
@@ -721,8 +437,13 @@ void PluginView::forceRedraw()
         gtk_widget_queue_draw(m_parentFrame->view()->hostWindow()->platformPageClient());
 }
 
-static Display* getPluginDisplay()
+Display* PluginView::getPluginDisplay(Frame* parentFrame)
 {
+    if (parentFrame) {
+        GtkWidget* widget = parentFrame->view()->hostWindow()->platformPageClient();
+        return GDK_DISPLAY_XDISPLAY(gtk_widget_get_display(widget));
+    }
+
     // 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
@@ -815,7 +536,7 @@ bool PluginView::platformStart()
             setPlatformWidget(gtk_xtbin_new(pageClient, 0));
     } else {
         setPlatformWidget(0);
-        m_pluginDisplay = getPluginDisplay();
+        m_pluginDisplay = getPluginDisplay(nullptr);
     }
 
     show();
diff --git a/Source/WebCore/plugins/x11/PluginViewX11.cpp b/Source/WebCore/plugins/x11/PluginViewX11.cpp
new file mode 100644 (file)
index 0000000..934fbca
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2008 Collabora Ltd. All rights reserved.
+ * Copyright (C) 2009, 2010 Kakai, Inc. <brian@kakai.com>
+ * Copyright (C) 2010 Igalia S.L.
+ * Copyright (C) 2014 Samsung Electronics
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "PluginView.h"
+
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "JSDOMWindowBase.h"
+#include "PlatformContextCairo.h"
+#include "PluginPackage.h"
+#include "RefPtrCairo.h"
+#include <X11/X.h>
+#include <cairo-xlib.h>
+#include <runtime/JSLock.h>
+
+#if PLATFORM(GTK)
+#define String XtStringType
+#include "gtk2xtbin.h"
+#endif
+
+#define Bool int // this became undefined in npruntime_internal.h
+#define None 0L // ditto
+#define Status int // ditto
+#include <X11/extensions/Xrender.h>
+
+namespace WebCore {
+
+bool PluginView::dispatchNPEvent(NPEvent& event)
+{
+    if (!m_plugin->pluginFuncs()->event)
+        return false;
+
+    PluginView::setCurrentPluginView(this);
+    JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonVM());
+    setCallingPlugin(true);
+
+    bool accepted = m_plugin->pluginFuncs()->event(m_instance, &event);
+
+    setCallingPlugin(false);
+    PluginView::setCurrentPluginView(0);
+    return accepted;
+}
+
+void PluginView::updatePluginWidget()
+{
+    if (!parent())
+        return;
+
+    ASSERT(parent()->isFrameView());
+    FrameView* frameView = toFrameView(parent());
+
+    IntRect oldWindowRect = m_windowRect;
+    IntRect oldClipRect = m_clipRect;
+
+    m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
+    m_clipRect = windowClipRect();
+    m_clipRect.move(-m_windowRect.x(), -m_windowRect.y());
+
+    if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect)
+        return;
+
+    if (m_status != PluginStatusLoadedSuccessfully)
+        return;
+
+    if (!m_isWindowed && !m_windowRect.isEmpty()) {
+        Display* display = getPluginDisplay(nullptr);
+        if (m_drawable)
+            XFreePixmap(display, m_drawable);
+            
+        m_drawable = XCreatePixmap(display, getRootWindow(m_parentFrame.get()),
+            m_windowRect.width(), m_windowRect.height(),
+            ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth);
+        XSync(display, false); // make sure that the server knows about the Drawable
+    }
+
+    setNPWindowIfNeeded();
+}
+
+void PluginView::handleFocusInEvent()
+{
+    if (!m_isStarted || m_status != PluginStatusLoadedSuccessfully)
+        return;
+
+    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::invalidateRect(NPRect* rect)
+{
+    if (!rect) {
+        invalidate();
+        return;
+    }
+
+    IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top);
+    invalidateWindowlessPluginRect(r);
+}
+
+void PluginView::invalidateRegion(NPRegion)
+{
+    invalidate();
+}
+
+void PluginView::handleFocusOutEvent()
+{
+    if (!m_isStarted || m_status != PluginStatusLoadedSuccessfully)
+        return;
+
+    XEvent npEvent;
+    initXEvent(&npEvent);
+
+    XFocusChangeEvent& event = npEvent.xfocus;
+    event.type = 10; // FocusOut gets unset somewhere
+    event.mode = NotifyNormal;
+    event.detail = NotifyDetailNone;
+
+    dispatchNPEvent(npEvent);
+}
+
+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 = getPluginDisplay(m_parentFrame.get());
+
+    // Mozilla also sends None here for windowless plugins. See nsObjectFrame.cpp in the Mozilla sources.
+    // This method also sets up FocusIn and FocusOut events for windows plugins, but Mozilla doesn't
+    // even send these types of events to windowed plugins. In the future, it may be good to only
+    // send them to windowless plugins.
+    xEvent->xany.window = None;
+}
+
+void PluginView::paint(GraphicsContext* context, const IntRect& rect)
+{
+    if (!m_isStarted || m_status != PluginStatusLoadedSuccessfully) {
+        paintMissingPluginIcon(context, rect);
+        return;
+    }
+
+    if (context->paintingDisabled())
+        return;
+
+    setNPWindowIfNeeded();
+
+    if (m_isWindowed)
+        return;
+
+    if (!m_drawable)
+        return;
+
+    Display* display = getPluginDisplay(nullptr);
+    const bool syncX = m_pluginDisplay && m_pluginDisplay != display;
+
+    IntRect exposedRect(rect);
+    exposedRect.intersect(frameRect());
+    exposedRect.move(-frameRect().x(), -frameRect().y());
+
+    RefPtr<cairo_surface_t> drawableSurface = adoptRef(cairo_xlib_surface_create(display,
+        m_drawable, m_visual, m_windowRect.width(), m_windowRect.height()));
+
+    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.
+        RefPtr<cairo_t> cr = adoptRef(cairo_create(drawableSurface.get()));
+
+        if (!(cairo_surface_get_content(drawableSurface.get()) & CAIRO_CONTENT_ALPHA)) {
+            // 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.
+
+            // This Would not work without double buffering, but we always use it.
+            cairo_set_source_surface(cr.get(), cairo_get_group_target(context->platformContext()->cr()),
+                -m_windowRect.x(), -m_windowRect.y());
+            cairo_set_operator(cr.get(), CAIRO_OPERATOR_SOURCE);
+        } else
+            cairo_set_operator(cr.get(), CAIRO_OPERATOR_CLEAR);
+
+        cairo_rectangle(cr.get(), exposedRect.x(), exposedRect.y(),
+            exposedRect.width(), exposedRect.height());
+        cairo_fill(cr.get());
+    }
+
+    XEvent xevent;
+    memset(&xevent, 0, sizeof(XEvent));
+    XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose;
+    exposeEvent.type = GraphicsExpose;
+    exposeEvent.display = 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
+
+    dispatchNPEvent(xevent);
+
+    if (syncX)
+        XSync(m_pluginDisplay, false); // sync changes by plugin
+
+    cairo_t* cr = context->platformContext()->cr();
+    cairo_save(cr);
+
+    cairo_set_source_surface(cr, drawableSurface.get(), 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);
+}
+
+void PluginView::setParent(ScrollView* parent)
+{
+    Widget::setParent(parent);
+
+    if (parent)
+        init();
+}
+
+void PluginView::setNPWindowRect(const IntRect&)
+{
+    if (!m_isWindowed)
+        setNPWindowIfNeeded();
+}
+
+void PluginView::setNPWindowIfNeeded()
+{
+    if (!m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow)
+        return;
+
+    // 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;
+
+    // Check if the platformPluginWidget still exists
+    if (m_isWindowed && !platformPluginWidget())
+        return;
+
+    if (m_clipRect.isEmpty()) {
+        // If width or height are null, set the clipRect to null,
+        // indicating that the plugin is not visible/scrolled out.
+        m_npWindow.clipRect.left = 0;
+        m_npWindow.clipRect.right = 0;
+        m_npWindow.clipRect.top = 0;
+        m_npWindow.clipRect.bottom = 0;
+    } else {
+        // Clipping rectangle of the plug-in; the origin is the top left corner of the drawable or window. 
+        m_npWindow.clipRect.left = m_npWindow.x + m_clipRect.x();
+        m_npWindow.clipRect.top = m_npWindow.y + m_clipRect.y();
+        m_npWindow.clipRect.right = m_npWindow.x + m_clipRect.x() + m_clipRect.width();
+        m_npWindow.clipRect.bottom = m_npWindow.y + m_clipRect.y() + m_clipRect.height();
+    }
+
+    // FLASH WORKAROUND: Only set initially. Multiple calls to
+    // setNPWindow() cause the plugin to crash in windowed mode.
+    if (!m_plugin->quirks().contains(PluginQuirkDontCallSetWindowMoreThanOnce) || !m_isWindowed
+        || m_npWindow.width == static_cast<uint32_t>(-1) || m_npWindow.height == static_cast<uint32_t>(-1)) {
+        m_npWindow.width = m_windowRect.width();
+        m_npWindow.height = m_windowRect.height();
+    }
+
+    PluginView::setCurrentPluginView(this);
+    JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonVM());
+    setCallingPlugin(true);
+    m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
+    setCallingPlugin(false);
+    PluginView::setCurrentPluginView(0);
+
+    if (!m_isWindowed)
+        return;
+
+#if PLATFORM(GTK)
+    // GtkXtBin will call gtk_widget_size_allocate, so we don't need to do it here.
+    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());
+        return;
+    }
+
+    m_delayedAllocation = m_windowRect;
+    updateWidgetAllocationAndClip();
+#endif
+}
+} // namespace WebCore