2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
4 * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "PluginView.h"
32 #include "BridgeJSC.h"
35 #include "ChromeClient.h"
37 #include "DocumentLoader.h"
39 #include "FloatPoint.h"
40 #include "FocusController.h"
42 #include "FrameLoadRequest.h"
43 #include "FrameLoader.h"
44 #include "FrameTree.h"
45 #include "FrameView.h"
46 #include "GraphicsContext.h"
47 #include "HTMLNames.h"
48 #include "HTMLPlugInElement.h"
49 #include "HostWindow.h"
50 #include "IFrameShimSupport.h"
53 #include "JSDOMBinding.h"
55 #include "KeyboardEvent.h"
56 #include "MouseEvent.h"
57 #include "NotImplemented.h"
59 #include "PlatformMouseEvent.h"
60 #include "PlatformKeyboardEvent.h"
61 #include "PluginContainerQt.h"
62 #include "PluginDebug.h"
63 #include "PluginPackage.h"
64 #include "PluginMainThreadScheduler.h"
65 #include "QWebPageClient.h"
66 #include "RenderLayer.h"
68 #include "npruntime_impl.h"
70 #include "runtime_root.h"
73 #include <QApplication>
74 #include <QDesktopWidget>
75 #include <QGraphicsWidget>
78 #include <QStyleOptionGraphicsItem>
85 #include <X11/extensions/Xrender.h>
87 #include <runtime/JSLock.h>
88 #include <runtime/JSValue.h>
92 using JSC::Interpreter;
104 bool PluginView::s_isRunningUnderDRT = false;
106 using namespace HTMLNames;
108 #if USE(ACCELERATED_COMPOSITING)
109 // Qt's GraphicsLayer (GraphicsLayerQt) requires layers to be QGraphicsWidgets
110 class PluginGraphicsLayerQt : public QGraphicsWidget {
112 PluginGraphicsLayerQt(PluginView* view) : m_view(view) { }
113 ~PluginGraphicsLayerQt() { }
115 void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0)
118 m_view->paintUsingXPixmap(painter, option->exposedRect.toRect());
125 bool PluginView::shouldUseAcceleratedCompositing() const
127 return m_parentFrame->page()->chrome()->client()->allowsAcceleratedCompositing()
128 && m_parentFrame->page()->settings()
129 && m_parentFrame->page()->settings()->acceleratedCompositingEnabled();
133 void PluginView::updatePluginWidget()
138 ASSERT(parent()->isFrameView());
139 FrameView* frameView = static_cast<FrameView*>(parent());
141 IntRect oldWindowRect = m_windowRect;
142 IntRect oldClipRect = m_clipRect;
144 m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
145 m_clipRect = windowClipRect();
146 m_clipRect.move(-m_windowRect.x(), -m_windowRect.y());
148 if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect)
151 // The plugin had a zero width or height before but was resized, we need to show it again.
152 if (oldWindowRect.isEmpty())
155 if (!m_isWindowed && m_windowRect.size() != oldWindowRect.size()) {
157 XFreePixmap(QX11Info::display(), m_drawable);
159 m_drawable = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), m_windowRect.width(), m_windowRect.height(),
160 ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth);
161 QApplication::syncX(); // make sure that the server knows about the Drawable
164 // do not call setNPWindowIfNeeded immediately, will be called on paint()
165 m_hasPendingGeometryChange = true;
167 // (i) in order to move/resize the plugin window at the same time as the
168 // rest of frame during e.g. scrolling, we set the window geometry
169 // in the paint() function, but as paint() isn't called when the
170 // plugin window is outside the frame which can be caused by a
171 // scroll, we need to move/resize immediately.
172 // (ii) if we are running layout tests from DRT, paint() won't ever get called
173 // so we need to call setNPWindowIfNeeded() if window geometry has changed
174 if (!m_windowRect.intersects(frameView->frameRect())
175 || (s_isRunningUnderDRT && platformPluginWidget() && (m_windowRect != oldWindowRect || m_clipRect != oldClipRect)))
176 setNPWindowIfNeeded();
178 if (!m_platformLayer) {
179 // Make sure we get repainted afterwards. This is necessary for downward
180 // scrolling to move the plugin widget properly.
181 // Note that we don't invalidate the frameRect() here. This is because QWebFrame::renderRelativeCoords()
182 // imitates ScrollView and adds the scroll offset back on to the rect we damage here (making the co-ordinates absolute
183 // to the frame again) before passing it to FrameView.
188 void PluginView::setFocus(bool focused)
190 if (platformPluginWidget()) {
192 platformPluginWidget()->setFocus(Qt::OtherFocusReason);
194 Widget::setFocus(focused);
198 void PluginView::show()
200 Q_ASSERT(platformPluginWidget() == platformWidget());
204 void PluginView::hide()
206 Q_ASSERT(platformPluginWidget() == platformWidget());
210 void PluginView::paintUsingXPixmap(QPainter* painter, const QRect &exposedRect)
212 QPixmap qtDrawable = QPixmap::fromX11Pixmap(m_drawable, QPixmap::ExplicitlyShared);
213 const int drawableDepth = ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth;
214 ASSERT(drawableDepth == qtDrawable.depth());
215 const bool syncX = m_pluginDisplay && m_pluginDisplay != QX11Info::display();
217 // When printing, Qt uses a QPicture to capture the output in preview mode. The
218 // QPicture holds a reference to the X Pixmap. As a result, the print preview would
219 // update itself when the X Pixmap changes. To prevent this, we create a copy.
220 if (m_element->document()->printing())
221 qtDrawable = qtDrawable.copy();
223 if (m_isTransparent && drawableDepth != 32) {
224 // Attempt content propagation for drawable with no alpha by copying over from the backing store
226 QPaintDevice* backingStoreDevice = QPainter::redirected(painter->device(), &offset);
227 offset = -offset; // negating the offset gives us the offset of the view within the backing store pixmap
229 const bool hasValidBackingStore = backingStoreDevice && backingStoreDevice->devType() == QInternal::Pixmap;
230 QPixmap* backingStorePixmap = static_cast<QPixmap*>(backingStoreDevice);
232 // We cannot grab contents from the backing store when painting on QGraphicsView items
233 // (because backing store contents are already transformed). What we really mean to do
234 // here is to check if we are painting on QWebView, but let's be a little permissive :)
235 QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
236 const bool backingStoreHasUntransformedContents = client && qobject_cast<QWidget*>(client->pluginParent());
238 if (hasValidBackingStore && backingStorePixmap->depth() == drawableDepth
239 && backingStoreHasUntransformedContents) {
240 GC gc = XDefaultGC(QX11Info::display(), QX11Info::appScreen());
241 XCopyArea(QX11Info::display(), backingStorePixmap->handle(), m_drawable, gc,
242 offset.x() + m_windowRect.x() + exposedRect.x(), offset.y() + m_windowRect.y() + exposedRect.y(),
243 exposedRect.width(), exposedRect.height(), exposedRect.x(), exposedRect.y());
244 } else { // no backing store, clean the pixmap because the plugin thinks its transparent
245 QPainter painter(&qtDrawable);
246 painter.fillRect(exposedRect, Qt::white);
250 QApplication::syncX();
254 memset(&xevent, 0, sizeof(XEvent));
255 XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose;
256 exposeEvent.type = GraphicsExpose;
257 exposeEvent.display = QX11Info::display();
258 exposeEvent.drawable = qtDrawable.handle();
259 exposeEvent.x = exposedRect.x();
260 exposeEvent.y = exposedRect.y();
261 exposeEvent.width = exposedRect.x() + exposedRect.width(); // flash bug? it thinks width is the right in transparent mode
262 exposeEvent.height = exposedRect.y() + exposedRect.height(); // flash bug? it thinks height is the bottom in transparent mode
264 dispatchNPEvent(xevent);
267 XSync(m_pluginDisplay, false); // sync changes by plugin
269 painter->drawPixmap(QPoint(exposedRect.x(), exposedRect.y()), qtDrawable, exposedRect);
272 void PluginView::paint(GraphicsContext* context, const IntRect& rect)
275 paintMissingPluginIcon(context, rect);
279 if (context->paintingDisabled())
282 setNPWindowIfNeeded();
287 #if USE(ACCELERATED_COMPOSITING)
295 QPainter* painter = context->platformContext();
296 IntRect exposedRect(rect);
297 exposedRect.intersect(frameRect());
298 exposedRect.move(-frameRect().x(), -frameRect().y());
300 painter->translate(frameRect().x(), frameRect().y());
301 paintUsingXPixmap(painter, exposedRect);
302 painter->translate(-frameRect().x(), -frameRect().y());
305 // TODO: Unify across ports.
306 bool PluginView::dispatchNPEvent(NPEvent& event)
308 if (!m_plugin->pluginFuncs()->event)
311 bool shouldPop = false;
313 if (m_plugin->pluginFuncs()->version < NPVERS_HAS_POPUPS_ENABLED_STATE
314 && (event.type == ButtonRelease || event.type == 3 /*KeyRelease*/)) {
315 pushPopupsEnabledState(true);
319 PluginView::setCurrentPluginView(this);
321 JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
323 setCallingPlugin(true);
324 bool accepted = !m_plugin->pluginFuncs()->event(m_instance, &event);
325 setCallingPlugin(false);
326 PluginView::setCurrentPluginView(0);
329 popPopupsEnabledState();
334 void setSharedXEventFields(XEvent* xEvent, QWidget* ownerWidget)
336 xEvent->xany.serial = 0; // we are unaware of the last request processed by X Server
337 xEvent->xany.send_event = false;
338 xEvent->xany.display = QX11Info::display();
339 // NOTE: event->xany.window doesn't always respond to the .window property of other XEvent's
340 // but does in the case of KeyPress, KeyRelease, ButtonPress, ButtonRelease, and MotionNotify
341 // events; thus, this is right:
342 xEvent->xany.window = ownerWidget ? ownerWidget->window()->handle() : 0;
345 void PluginView::initXEvent(XEvent* xEvent)
347 memset(xEvent, 0, sizeof(XEvent));
349 QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
350 QWidget* ownerWidget = client ? client->ownerWidget() : 0;
351 setSharedXEventFields(xEvent, ownerWidget);
354 void PluginView::setXKeyEventSpecificFields(XEvent* xEvent, KeyboardEvent* event)
356 const PlatformKeyboardEvent* keyEvent = event->keyEvent();
358 xEvent->type = (event->type() == eventNames().keydownEvent) ? 2 : 3; // ints as Qt unsets KeyPress and KeyRelease
359 xEvent->xkey.root = QX11Info::appRootWindow();
360 xEvent->xkey.subwindow = 0; // we have no child window
361 xEvent->xkey.time = event->timeStamp();
362 xEvent->xkey.state = keyEvent->nativeModifiers();
363 xEvent->xkey.keycode = keyEvent->nativeScanCode();
365 // We may not have a nativeScanCode() if the key event is from DRT's eventsender. In that
366 // case fetch the XEvent's keycode from the event's text. The only
367 // place this keycode will be used is in webkit_test_plugin_handle_event().
368 // FIXME: Create Qt API so that we can set the appropriate keycode in DRT EventSender instead.
369 if (s_isRunningUnderDRT && !xEvent->xkey.keycode) {
370 QKeyEvent* qKeyEvent = keyEvent->qtEvent();
372 QString keyText = qKeyEvent->text().left(1);
373 xEvent->xkey.keycode = XKeysymToKeycode(QX11Info::display(), XStringToKeysym(keyText.toUtf8().constData()));
376 xEvent->xkey.same_screen = true;
378 // NOTE: As the XEvents sent to the plug-in are synthesized and there is not a native window
379 // corresponding to the plug-in rectangle, some of the members of the XEvent structures are not
380 // set to their normal Xserver values. e.g. Key events don't have a position.
381 // source: https://developer.mozilla.org/en/NPEvent
384 xEvent->xkey.x_root = 0;
385 xEvent->xkey.y_root = 0;
388 void PluginView::handleKeyboardEvent(KeyboardEvent* event)
393 if (event->type() != eventNames().keydownEvent && event->type() != eventNames().keyupEvent)
397 initXEvent(&npEvent);
398 setXKeyEventSpecificFields(&npEvent, event);
400 if (dispatchNPEvent(npEvent))
401 event->setDefaultHandled();
404 static unsigned int inputEventState(MouseEvent* event)
406 unsigned int state = 0;
407 if (event->ctrlKey())
408 state |= ControlMask;
409 if (event->shiftKey())
413 if (event->metaKey())
418 static void setXButtonEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos)
420 XButtonEvent& xbutton = xEvent->xbutton;
421 xbutton.type = event->type() == eventNames().mousedownEvent ? ButtonPress : ButtonRelease;
422 xbutton.root = QX11Info::appRootWindow();
423 xbutton.subwindow = 0;
424 xbutton.time = event->timeStamp();
425 xbutton.x = postZoomPos.x();
426 xbutton.y = postZoomPos.y();
427 xbutton.x_root = event->screenX();
428 xbutton.y_root = event->screenY();
429 xbutton.state = inputEventState(event);
430 switch (event->button()) {
432 xbutton.button = Button2;
435 xbutton.button = Button3;
439 xbutton.button = Button1;
442 xbutton.same_screen = true;
445 static void setXMotionEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos)
447 XMotionEvent& xmotion = xEvent->xmotion;
448 xmotion.type = MotionNotify;
449 xmotion.root = QX11Info::appRootWindow();
450 xmotion.subwindow = 0;
451 xmotion.time = event->timeStamp();
452 xmotion.x = postZoomPos.x();
453 xmotion.y = postZoomPos.y();
454 xmotion.x_root = event->screenX();
455 xmotion.y_root = event->screenY();
456 xmotion.state = inputEventState(event);
457 xmotion.is_hint = NotifyNormal;
458 xmotion.same_screen = true;
461 static void setXCrossingEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos)
463 XCrossingEvent& xcrossing = xEvent->xcrossing;
464 xcrossing.type = event->type() == eventNames().mouseoverEvent ? EnterNotify : LeaveNotify;
465 xcrossing.root = QX11Info::appRootWindow();
466 xcrossing.subwindow = 0;
467 xcrossing.time = event->timeStamp();
468 xcrossing.x = postZoomPos.y();
469 xcrossing.y = postZoomPos.x();
470 xcrossing.x_root = event->screenX();
471 xcrossing.y_root = event->screenY();
472 xcrossing.state = inputEventState(event);
473 xcrossing.mode = NotifyNormal;
474 xcrossing.detail = NotifyDetailNone;
475 xcrossing.same_screen = true;
476 xcrossing.focus = false;
479 void PluginView::handleMouseEvent(MouseEvent* event)
484 if (event->button() == RightButton && m_plugin->quirks().contains(PluginQuirkIgnoreRightClickInWindowlessMode))
487 if (event->type() == eventNames().mousedownEvent) {
488 // Give focus to the plugin on click
489 if (Page* page = m_parentFrame->page())
490 page->focusController()->setActive(true);
492 focusPluginElement();
496 initXEvent(&npEvent);
498 IntPoint postZoomPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation()));
500 if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent)
501 setXButtonEventSpecificFields(&npEvent, event, postZoomPos);
502 else if (event->type() == eventNames().mousemoveEvent)
503 setXMotionEventSpecificFields(&npEvent, event, postZoomPos);
504 else if (event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mouseoverEvent)
505 setXCrossingEventSpecificFields(&npEvent, event, postZoomPos);
509 if (dispatchNPEvent(npEvent))
510 event->setDefaultHandled();
513 void PluginView::handleFocusInEvent()
516 initXEvent(&npEvent);
518 XFocusChangeEvent& event = npEvent.xfocus;
519 event.type = 9; /* int as Qt unsets FocusIn */
520 event.mode = NotifyNormal;
521 event.detail = NotifyDetailNone;
523 dispatchNPEvent(npEvent);
526 void PluginView::handleFocusOutEvent()
529 initXEvent(&npEvent);
531 XFocusChangeEvent& event = npEvent.xfocus;
532 event.type = 10; /* int as Qt unsets FocusOut */
533 event.mode = NotifyNormal;
534 event.detail = NotifyDetailNone;
536 dispatchNPEvent(npEvent);
539 void PluginView::setParent(ScrollView* parent)
541 Widget::setParent(parent);
547 void PluginView::setNPWindowRect(const IntRect&)
550 setNPWindowIfNeeded();
553 void PluginView::setNPWindowIfNeeded()
555 if (!m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow)
558 // If the plugin didn't load sucessfully, no point in calling setwindow
559 if (m_status != PluginStatusLoadedSuccessfully)
562 // On Unix, only call plugin if it's full-page or windowed
563 if (m_mode != NP_FULL && m_mode != NP_EMBED)
566 // Check if the platformPluginWidget still exists
567 if (m_isWindowed && !platformPluginWidget())
570 if (!m_hasPendingGeometryChange)
572 m_hasPendingGeometryChange = false;
575 platformPluginWidget()->setGeometry(m_windowRect);
577 // Cut out areas of the plugin occluded by iframe shims
578 Vector<IntRect> cutOutRects;
579 QRegion clipRegion = QRegion(m_clipRect);
580 getPluginOcclusions(m_element, this->parent(), frameRect(), cutOutRects);
581 for (size_t i = 0; i < cutOutRects.size(); i++) {
582 cutOutRects[i].move(-frameRect().x(), -frameRect().y());
583 clipRegion = clipRegion.subtracted(QRegion(cutOutRects[i]));
585 // if setMask is set with an empty QRegion, no clipping will
586 // be performed, so in that case we hide the plugin view
587 platformPluginWidget()->setVisible(!clipRegion.isEmpty());
588 platformPluginWidget()->setMask(clipRegion);
590 m_npWindow.x = m_windowRect.x();
591 m_npWindow.y = m_windowRect.y();
597 // If the width or height are null, set the clipRect to null, indicating that
598 // the plugin is not visible/scrolled out.
599 if (!m_clipRect.width() || !m_clipRect.height()) {
600 m_npWindow.clipRect.left = 0;
601 m_npWindow.clipRect.right = 0;
602 m_npWindow.clipRect.top = 0;
603 m_npWindow.clipRect.bottom = 0;
605 // Clipping rectangle of the plug-in; the origin is the top left corner of the drawable or window.
606 m_npWindow.clipRect.left = m_npWindow.x + m_clipRect.x();
607 m_npWindow.clipRect.top = m_npWindow.y + m_clipRect.y();
608 m_npWindow.clipRect.right = m_npWindow.x + m_clipRect.x() + m_clipRect.width();
609 m_npWindow.clipRect.bottom = m_npWindow.y + m_clipRect.y() + m_clipRect.height();
612 if (m_plugin->quirks().contains(PluginQuirkDontCallSetWindowMoreThanOnce)) {
613 // FLASH WORKAROUND: Only set initially. Multiple calls to
614 // setNPWindow() cause the plugin to crash in windowed mode.
615 if (!m_isWindowed || m_npWindow.width == -1 || m_npWindow.height == -1) {
616 m_npWindow.width = m_windowRect.width();
617 m_npWindow.height = m_windowRect.height();
620 m_npWindow.width = m_windowRect.width();
621 m_npWindow.height = m_windowRect.height();
624 PluginView::setCurrentPluginView(this);
626 JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
628 setCallingPlugin(true);
629 m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
630 setCallingPlugin(false);
631 PluginView::setCurrentPluginView(0);
634 void PluginView::setParentVisible(bool visible)
636 if (isParentVisible() == visible)
639 Widget::setParentVisible(visible);
641 if (isSelfVisible() && platformPluginWidget())
642 platformPluginWidget()->setVisible(visible);
645 NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf)
647 String filename(buf, len);
649 if (filename.startsWith("file:///"))
650 filename = filename.substring(8);
653 if (!getFileSize(filename, size))
654 return NPERR_FILE_NOT_FOUND;
656 FILE* fileHandle = fopen((filename.utf8()).data(), "r");
658 return NPERR_FILE_NOT_FOUND;
661 int bytesRead = fread(buffer.data(), 1, size, fileHandle);
666 return NPERR_FILE_NOT_FOUND;
668 return NPERR_NO_ERROR;
671 bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPError* result)
675 *static_cast<uint32_t*>(value) = 0;
676 *result = NPERR_NO_ERROR;
679 case NPNVSupportsXEmbedBool:
680 *static_cast<NPBool*>(value) = true;
681 *result = NPERR_NO_ERROR;
684 case NPNVjavascriptEnabledBool:
685 *static_cast<NPBool*>(value) = true;
686 *result = NPERR_NO_ERROR;
689 case NPNVSupportsWindowless:
690 *static_cast<NPBool*>(value) = true;
691 *result = NPERR_NO_ERROR;
699 bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result)
703 *(void **)value = QX11Info::display();
704 *result = NPERR_NO_ERROR;
707 case NPNVxtAppContext:
708 *result = NPERR_GENERIC_ERROR;
711 case NPNVnetscapeWindow: {
712 void* w = reinterpret_cast<void*>(value);
713 QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
714 *((XID *)w) = client ? client->ownerWidget()->window()->winId() : 0;
715 *result = NPERR_NO_ERROR;
720 if (m_plugin->quirks().contains(PluginQuirkRequiresGtkToolKit)) {
721 *((uint32_t *)value) = 2;
722 *result = NPERR_NO_ERROR;
732 void PluginView::invalidateRect(const IntRect& rect)
734 #if USE(ACCELERATED_COMPOSITING) && !USE(TEXTURE_MAPPER)
735 if (m_platformLayer) {
736 m_platformLayer->update(QRectF(rect));
742 if (platformWidget()) {
743 // update() will schedule a repaint of the widget so ensure
744 // its knowledge of its position on the page is up to date.
745 platformWidget()->setGeometry(m_windowRect);
746 platformWidget()->update(rect);
751 invalidateWindowlessPluginRect(rect);
754 void PluginView::invalidateRect(NPRect* rect)
760 IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top);
764 void PluginView::invalidateRegion(NPRegion region)
770 void PluginView::forceRedraw()
775 static Display *getPluginDisplay()
777 // The plugin toolkit might run using a different X connection. At the moment, we only
778 // support gdk based plugins (like flash) that use a different X connection.
779 // The code below has the same effect as this one:
780 // Display *gdkDisplay = gdk_x11_display_get_xdisplay(gdk_display_get_default());
781 QLibrary library(QLatin1String("libgdk-x11-2.0"), 0);
785 typedef void *(*gdk_init_check_ptr)(void*, void*);
786 gdk_init_check_ptr gdk_init_check = (gdk_init_check_ptr)library.resolve("gdk_init_check");
790 typedef void *(*gdk_display_get_default_ptr)();
791 gdk_display_get_default_ptr gdk_display_get_default = (gdk_display_get_default_ptr)library.resolve("gdk_display_get_default");
792 if (!gdk_display_get_default)
795 typedef void *(*gdk_x11_display_get_xdisplay_ptr)(void *);
796 gdk_x11_display_get_xdisplay_ptr gdk_x11_display_get_xdisplay = (gdk_x11_display_get_xdisplay_ptr)library.resolve("gdk_x11_display_get_xdisplay");
797 if (!gdk_x11_display_get_xdisplay)
800 gdk_init_check(0, 0);
801 return (Display*)gdk_x11_display_get_xdisplay(gdk_display_get_default());
804 static void getVisualAndColormap(int depth, Visual **visual, Colormap *colormap)
809 #ifndef QT_NO_XRENDER
810 static const bool useXRender = qgetenv("QT_X11_NO_XRENDER").isNull(); // Should also check for XRender >= 0.5
812 static const bool useXRender = false;
815 if (!useXRender && depth == 32)
820 templ.screen = QX11Info::appScreen();
822 templ.c_class = TrueColor;
823 XVisualInfo* xvi = XGetVisualInfo(QX11Info::display(), VisualScreenMask | VisualDepthMask | VisualClassMask, &templ, &nvi);
828 #ifndef QT_NO_XRENDER
830 for (int idx = 0; idx < nvi; ++idx) {
831 XRenderPictFormat* format = XRenderFindVisualFormat(QX11Info::display(), xvi[idx].visual);
832 if (format->type == PictTypeDirect && format->direct.alphaMask) {
833 *visual = xvi[idx].visual;
838 #endif // QT_NO_XRENDER
839 *visual = xvi[0].visual;
844 *colormap = XCreateColormap(QX11Info::display(), QX11Info::appRootWindow(), *visual, AllocNone);
847 bool PluginView::platformStart()
850 ASSERT(m_status == PluginStatusLoadedSuccessfully);
852 if (m_plugin->pluginFuncs()->getvalue) {
853 PluginView::setCurrentPluginView(this);
855 JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
857 setCallingPlugin(true);
858 m_plugin->pluginFuncs()->getvalue(m_instance, NPPVpluginNeedsXEmbed, &m_needsXEmbed);
859 setCallingPlugin(false);
860 PluginView::setCurrentPluginView(0);
864 QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
865 if (m_needsXEmbed && client) {
866 setPlatformWidget(new PluginContainerQt(this, client->ownerWidget()));
867 // sync our XEmbed container window creation before sending the xid to plugins.
868 QApplication::syncX();
871 m_status = PluginStatusCanNotLoadPlugin;
875 setPlatformWidget(0);
876 m_pluginDisplay = getPluginDisplay();
878 #if USE(ACCELERATED_COMPOSITING) && !USE(TEXTURE_MAPPER)
879 if (shouldUseAcceleratedCompositing()) {
880 m_platformLayer = adoptPtr(new PluginGraphicsLayerQt(this));
881 // Trigger layer computation in RenderLayerCompositor
882 m_element->setNeedsStyleRecalc(SyntheticStyleChange);
887 // If the width and the height are not zero we show the PluginView.
888 if (!frameRect().isEmpty())
891 NPSetWindowCallbackStruct* wsi = new NPSetWindowCallbackStruct();
895 const QX11Info* x11Info = &platformPluginWidget()->x11Info();
897 wsi->display = x11Info->display();
898 wsi->visual = (Visual*)x11Info->visual();
899 wsi->depth = x11Info->depth();
900 wsi->colormap = x11Info->colormap();
902 m_npWindow.type = NPWindowTypeWindow;
903 m_npWindow.window = (void*)platformPluginWidget()->winId();
904 m_npWindow.width = -1;
905 m_npWindow.height = -1;
907 const QX11Info* x11Info = &QApplication::desktop()->x11Info();
909 if (x11Info->depth() == 32 || !m_plugin->quirks().contains(PluginQuirkRequiresDefaultScreenDepth)) {
910 getVisualAndColormap(32, &m_visual, &m_colormap);
915 getVisualAndColormap(x11Info->depth(), &m_visual, &m_colormap);
916 wsi->depth = x11Info->depth();
919 wsi->display = x11Info->display();
920 wsi->visual = m_visual;
921 wsi->colormap = m_colormap;
923 m_npWindow.type = NPWindowTypeDrawable;
924 m_npWindow.window = 0; // Not used?
927 m_npWindow.width = -1;
928 m_npWindow.height = -1;
931 m_npWindow.ws_info = wsi;
933 if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall))) {
934 updatePluginWidget();
935 setNPWindowIfNeeded();
941 void PluginView::platformDestroy()
943 if (platformPluginWidget())
944 delete platformPluginWidget();
947 XFreePixmap(QX11Info::display(), m_drawable);
950 XFreeColormap(QX11Info::display(), m_colormap);
953 #if USE(ACCELERATED_COMPOSITING)
954 PlatformLayer* PluginView::platformLayer() const
956 return m_platformLayer.get();
960 } // namespace WebCore