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"
35 #include "DocumentLoader.h"
37 #include "FloatPoint.h"
38 #include "FocusController.h"
40 #include "FrameLoadRequest.h"
41 #include "FrameLoader.h"
42 #include "FrameTree.h"
43 #include "FrameView.h"
44 #include "GraphicsContext.h"
45 #include "HTMLNames.h"
46 #include "HTMLPlugInElement.h"
47 #include "HostWindow.h"
50 #include "JSDOMBinding.h"
52 #include "KeyboardEvent.h"
53 #include "MouseEvent.h"
54 #include "NotImplemented.h"
56 #include "PlatformMouseEvent.h"
57 #include "PlatformKeyboardEvent.h"
58 #include "PluginContainerQt.h"
59 #include "PluginDebug.h"
60 #include "PluginPackage.h"
61 #include "PluginMainThreadScheduler.h"
62 #include "QWebPageClient.h"
63 #include "RenderLayer.h"
64 #include "ScriptController.h"
66 #include "npruntime_impl.h"
67 #include "qwebpage_p.h"
68 #include "runtime_root.h"
70 #include <QApplication>
71 #include <QDesktopWidget>
80 #include <X11/extensions/Xrender.h>
82 #include <runtime/JSLock.h>
83 #include <runtime/JSValue.h>
86 using JSC::Interpreter;
97 using namespace HTMLNames;
99 void PluginView::updatePluginWidget()
104 ASSERT(parent()->isFrameView());
105 FrameView* frameView = static_cast<FrameView*>(parent());
107 IntRect oldWindowRect = m_windowRect;
108 IntRect oldClipRect = m_clipRect;
110 m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
111 m_clipRect = windowClipRect();
112 m_clipRect.move(-m_windowRect.x(), -m_windowRect.y());
114 if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect)
117 if (!m_isWindowed && m_windowRect.size() != oldWindowRect.size()) {
118 #if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5)
119 // On Maemo5, Flash always renders to 16-bit buffer
121 m_image = QImage(m_windowRect.width(), m_windowRect.height(), QImage::Format_RGB16);
126 XFreePixmap(QX11Info::display(), m_drawable);
128 m_drawable = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), m_windowRect.width(), m_windowRect.height(),
129 ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth);
130 QApplication::syncX(); // make sure that the server knows about the Drawable
134 // do not call setNPWindowIfNeeded immediately, will be called on paint()
135 m_hasPendingGeometryChange = true;
137 // (i) in order to move/resize the plugin window at the same time as the
138 // rest of frame during e.g. scrolling, we set the window geometry
139 // in the paint() function, but as paint() isn't called when the
140 // plugin window is outside the frame which can be caused by a
141 // scroll, we need to move/resize immediately.
142 // (ii) if we are running layout tests from DRT, paint() won't ever get called
143 // so we need to call setNPWindowIfNeeded() if window geometry has changed
144 if (!m_windowRect.intersects(frameView->frameRect())
145 || (QWebPagePrivate::drtRun && platformPluginWidget() && (m_windowRect != oldWindowRect || m_clipRect != oldClipRect)))
146 setNPWindowIfNeeded();
148 // Make sure we get repainted afterwards. This is necessary for downward
149 // scrolling to move the plugin widget properly.
153 void PluginView::setFocus(bool focused)
155 if (platformPluginWidget()) {
157 platformPluginWidget()->setFocus(Qt::OtherFocusReason);
159 Widget::setFocus(focused);
163 void PluginView::show()
165 Q_ASSERT(platformPluginWidget() == platformWidget());
169 void PluginView::hide()
171 Q_ASSERT(platformPluginWidget() == platformWidget());
175 #if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5)
176 void PluginView::paintUsingImageSurfaceExtension(QPainter* painter, const IntRect& exposedRect)
178 NPImageExpose imageExpose;
180 QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
181 const bool surfaceHasUntransformedContents = client && qobject_cast<QWidget*>(client->pluginParent());
183 QPaintDevice* surface = QPainter::redirected(painter->device(), &offset);
185 // If the surface is a QImage, we can render directly into it
186 if (surfaceHasUntransformedContents && surface && surface->devType() == QInternal::Image) {
187 QImage* image = static_cast<QImage*>(surface);
188 offset = -offset; // negating the offset gives us the offset of the view within the surface
189 imageExpose.data = reinterpret_cast<char*>(image->bits());
190 imageExpose.dataSize.width = image->width();
191 imageExpose.dataSize.height = image->height();
192 imageExpose.stride = image->bytesPerLine();
193 imageExpose.depth = image->depth(); // this is guaranteed to be 16 on Maemo5
194 imageExpose.translateX = offset.x() + m_windowRect.x();
195 imageExpose.translateY = offset.y() + m_windowRect.y();
196 imageExpose.scaleX = 1;
197 imageExpose.scaleY = 1;
199 if (m_isTransparent) {
200 // On Maemo5, Flash expects the buffer to contain the contents that are below it.
201 // We don't support transparency for non-raster graphicssystem, so clean the image
202 // before giving to Flash.
203 QPainter imagePainter(&m_image);
204 imagePainter.fillRect(exposedRect, Qt::white);
207 imageExpose.data = reinterpret_cast<char*>(m_image.bits());
208 imageExpose.dataSize.width = m_image.width();
209 imageExpose.dataSize.height = m_image.height();
210 imageExpose.stride = m_image.bytesPerLine();
211 imageExpose.depth = m_image.depth();
212 imageExpose.translateX = 0;
213 imageExpose.translateY = 0;
214 imageExpose.scaleX = 1;
215 imageExpose.scaleY = 1;
217 imageExpose.x = exposedRect.x();
218 imageExpose.y = exposedRect.y();
219 imageExpose.width = exposedRect.width();
220 imageExpose.height = exposedRect.height();
223 memset(&xevent, 0, sizeof(XEvent));
224 XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose;
225 exposeEvent.type = GraphicsExpose;
226 exposeEvent.display = 0;
227 exposeEvent.drawable = reinterpret_cast<XID>(&imageExpose);
228 exposeEvent.x = exposedRect.x();
229 exposeEvent.y = exposedRect.y();
230 exposeEvent.width = exposedRect.width();
231 exposeEvent.height = exposedRect.height();
233 dispatchNPEvent(xevent);
235 if (!surfaceHasUntransformedContents || !surface || surface->devType() != QInternal::Image)
236 painter->drawImage(QPoint(frameRect().x() + exposedRect.x(), frameRect().y() + exposedRect.y()), m_image, exposedRect);
240 void PluginView::paint(GraphicsContext* context, const IntRect& rect)
243 paintMissingPluginIcon(context, rect);
247 if (context->paintingDisabled())
250 setNPWindowIfNeeded();
256 #if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5)
262 QPainter* painter = context->platformContext();
263 IntRect exposedRect(rect);
264 exposedRect.intersect(frameRect());
265 exposedRect.move(-frameRect().x(), -frameRect().y());
267 #if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5)
268 if (!m_image.isNull()) {
269 paintUsingImageSurfaceExtension(painter, exposedRect);
274 QPixmap qtDrawable = QPixmap::fromX11Pixmap(m_drawable, QPixmap::ExplicitlyShared);
275 const int drawableDepth = ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth;
276 ASSERT(drawableDepth == qtDrawable.depth());
277 const bool syncX = m_pluginDisplay && m_pluginDisplay != QX11Info::display();
279 // When printing, Qt uses a QPicture to capture the output in preview mode. The
280 // QPicture holds a reference to the X Pixmap. As a result, the print preview would
281 // update itself when the X Pixmap changes. To prevent this, we create a copy.
282 if (m_element->document()->printing())
283 qtDrawable = qtDrawable.copy();
285 if (m_isTransparent && drawableDepth != 32) {
286 // Attempt content propagation for drawable with no alpha by copying over from the backing store
288 QPaintDevice* backingStoreDevice = QPainter::redirected(painter->device(), &offset);
289 offset = -offset; // negating the offset gives us the offset of the view within the backing store pixmap
291 const bool hasValidBackingStore = backingStoreDevice && backingStoreDevice->devType() == QInternal::Pixmap;
292 QPixmap* backingStorePixmap = static_cast<QPixmap*>(backingStoreDevice);
294 // We cannot grab contents from the backing store when painting on QGraphicsView items
295 // (because backing store contents are already transformed). What we really mean to do
296 // here is to check if we are painting on QWebView, but let's be a little permissive :)
297 QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
298 const bool backingStoreHasUntransformedContents = client && qobject_cast<QWidget*>(client->pluginParent());
300 if (hasValidBackingStore && backingStorePixmap->depth() == drawableDepth
301 && backingStoreHasUntransformedContents) {
302 GC gc = XDefaultGC(QX11Info::display(), QX11Info::appScreen());
303 XCopyArea(QX11Info::display(), backingStorePixmap->handle(), m_drawable, gc,
304 offset.x() + m_windowRect.x() + exposedRect.x(), offset.y() + m_windowRect.y() + exposedRect.y(),
305 exposedRect.width(), exposedRect.height(), exposedRect.x(), exposedRect.y());
306 } else { // no backing store, clean the pixmap because the plugin thinks its transparent
307 QPainter painter(&qtDrawable);
308 painter.fillRect(exposedRect, Qt::white);
312 QApplication::syncX();
316 memset(&xevent, 0, sizeof(XEvent));
317 XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose;
318 exposeEvent.type = GraphicsExpose;
319 exposeEvent.display = QX11Info::display();
320 exposeEvent.drawable = qtDrawable.handle();
321 exposeEvent.x = exposedRect.x();
322 exposeEvent.y = exposedRect.y();
323 exposeEvent.width = exposedRect.x() + exposedRect.width(); // flash bug? it thinks width is the right in transparent mode
324 exposeEvent.height = exposedRect.y() + exposedRect.height(); // flash bug? it thinks height is the bottom in transparent mode
326 dispatchNPEvent(xevent);
329 XSync(m_pluginDisplay, false); // sync changes by plugin
331 painter->drawPixmap(QPoint(frameRect().x() + exposedRect.x(), frameRect().y() + exposedRect.y()), qtDrawable,
335 // TODO: Unify across ports.
336 bool PluginView::dispatchNPEvent(NPEvent& event)
338 if (!m_plugin->pluginFuncs()->event)
341 PluginView::setCurrentPluginView(this);
343 JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
345 setCallingPlugin(true);
346 bool accepted = m_plugin->pluginFuncs()->event(m_instance, &event);
347 setCallingPlugin(false);
348 PluginView::setCurrentPluginView(0);
353 void setSharedXEventFields(XEvent* xEvent, QWidget* ownerWidget)
355 xEvent->xany.serial = 0; // we are unaware of the last request processed by X Server
356 xEvent->xany.send_event = false;
357 xEvent->xany.display = QX11Info::display();
358 // NOTE: event->xany.window doesn't always respond to the .window property of other XEvent's
359 // but does in the case of KeyPress, KeyRelease, ButtonPress, ButtonRelease, and MotionNotify
360 // events; thus, this is right:
361 xEvent->xany.window = ownerWidget ? ownerWidget->window()->handle() : 0;
364 void PluginView::initXEvent(XEvent* xEvent)
366 memset(xEvent, 0, sizeof(XEvent));
368 QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
369 QWidget* ownerWidget = client ? client->ownerWidget() : 0;
370 setSharedXEventFields(xEvent, ownerWidget);
373 void setXKeyEventSpecificFields(XEvent* xEvent, KeyboardEvent* event)
375 QKeyEvent* qKeyEvent = event->keyEvent()->qtEvent();
377 xEvent->type = (event->type() == eventNames().keydownEvent) ? 2 : 3; // ints as Qt unsets KeyPress and KeyRelease
378 xEvent->xkey.root = QX11Info::appRootWindow();
379 xEvent->xkey.subwindow = 0; // we have no child window
380 xEvent->xkey.time = event->timeStamp();
381 xEvent->xkey.state = qKeyEvent->nativeModifiers();
382 xEvent->xkey.keycode = qKeyEvent->nativeScanCode();
384 // We may not have a nativeScanCode() if the key event is from DRT's eventsender. In that
385 // case just populate the XEvent's keycode with the Qt platform-independent keycode. The only
386 // place this keycode will be used is in webkit_test_plugin_handle_event().
387 if (QWebPagePrivate::drtRun && !xEvent->xkey.keycode) {
388 if (!qKeyEvent->text().isEmpty())
389 xEvent->xkey.keycode = int(qKeyEvent->text().at(0).unicode() + qKeyEvent->modifiers());
390 else if (qKeyEvent->key() && (qKeyEvent->key() != Qt::Key_unknown))
391 xEvent->xkey.keycode = int(qKeyEvent->key() + qKeyEvent->modifiers());
394 xEvent->xkey.same_screen = true;
396 // NOTE: As the XEvents sent to the plug-in are synthesized and there is not a native window
397 // corresponding to the plug-in rectangle, some of the members of the XEvent structures are not
398 // set to their normal Xserver values. e.g. Key events don't have a position.
399 // source: https://developer.mozilla.org/en/NPEvent
402 xEvent->xkey.x_root = 0;
403 xEvent->xkey.y_root = 0;
406 void PluginView::handleKeyboardEvent(KeyboardEvent* event)
411 if (event->type() != eventNames().keydownEvent && event->type() != eventNames().keyupEvent)
415 initXEvent(&npEvent);
416 setXKeyEventSpecificFields(&npEvent, event);
418 if (!dispatchNPEvent(npEvent))
419 event->setDefaultHandled();
422 static unsigned int inputEventState(MouseEvent* event)
424 unsigned int state = 0;
425 if (event->ctrlKey())
426 state |= ControlMask;
427 if (event->shiftKey())
431 if (event->metaKey())
436 static void setXButtonEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos)
438 XButtonEvent& xbutton = xEvent->xbutton;
439 xbutton.type = event->type() == eventNames().mousedownEvent ? ButtonPress : ButtonRelease;
440 xbutton.root = QX11Info::appRootWindow();
441 xbutton.subwindow = 0;
442 xbutton.time = event->timeStamp();
443 xbutton.x = postZoomPos.x();
444 xbutton.y = postZoomPos.y();
445 xbutton.x_root = event->screenX();
446 xbutton.y_root = event->screenY();
447 xbutton.state = inputEventState(event);
448 switch (event->button()) {
450 xbutton.button = Button2;
453 xbutton.button = Button3;
457 xbutton.button = Button1;
460 xbutton.same_screen = true;
463 static void setXMotionEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos)
465 XMotionEvent& xmotion = xEvent->xmotion;
466 xmotion.type = MotionNotify;
467 xmotion.root = QX11Info::appRootWindow();
468 xmotion.subwindow = 0;
469 xmotion.time = event->timeStamp();
470 xmotion.x = postZoomPos.x();
471 xmotion.y = postZoomPos.y();
472 xmotion.x_root = event->screenX();
473 xmotion.y_root = event->screenY();
474 xmotion.state = inputEventState(event);
475 xmotion.is_hint = NotifyNormal;
476 xmotion.same_screen = true;
479 static void setXCrossingEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos)
481 XCrossingEvent& xcrossing = xEvent->xcrossing;
482 xcrossing.type = event->type() == eventNames().mouseoverEvent ? EnterNotify : LeaveNotify;
483 xcrossing.root = QX11Info::appRootWindow();
484 xcrossing.subwindow = 0;
485 xcrossing.time = event->timeStamp();
486 xcrossing.x = postZoomPos.y();
487 xcrossing.y = postZoomPos.x();
488 xcrossing.x_root = event->screenX();
489 xcrossing.y_root = event->screenY();
490 xcrossing.state = inputEventState(event);
491 xcrossing.mode = NotifyNormal;
492 xcrossing.detail = NotifyDetailNone;
493 xcrossing.same_screen = true;
494 xcrossing.focus = false;
497 void PluginView::handleMouseEvent(MouseEvent* event)
502 if (event->type() == eventNames().mousedownEvent) {
503 // Give focus to the plugin on click
504 if (Page* page = m_parentFrame->page())
505 page->focusController()->setActive(true);
507 focusPluginElement();
511 initXEvent(&npEvent);
513 IntPoint postZoomPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation()));
515 if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent)
516 setXButtonEventSpecificFields(&npEvent, event, postZoomPos);
517 else if (event->type() == eventNames().mousemoveEvent)
518 setXMotionEventSpecificFields(&npEvent, event, postZoomPos);
519 else if (event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mouseoverEvent)
520 setXCrossingEventSpecificFields(&npEvent, event, postZoomPos);
524 if (!dispatchNPEvent(npEvent))
525 event->setDefaultHandled();
528 void PluginView::handleFocusInEvent()
531 initXEvent(&npEvent);
533 XFocusChangeEvent& event = npEvent.xfocus;
534 event.type = 9; /* int as Qt unsets FocusIn */
535 event.mode = NotifyNormal;
536 event.detail = NotifyDetailNone;
538 dispatchNPEvent(npEvent);
541 void PluginView::handleFocusOutEvent()
544 initXEvent(&npEvent);
546 XFocusChangeEvent& event = npEvent.xfocus;
547 event.type = 10; /* int as Qt unsets FocusOut */
548 event.mode = NotifyNormal;
549 event.detail = NotifyDetailNone;
551 dispatchNPEvent(npEvent);
554 void PluginView::setParent(ScrollView* parent)
556 Widget::setParent(parent);
562 void PluginView::setNPWindowRect(const IntRect&)
565 setNPWindowIfNeeded();
568 void PluginView::setNPWindowIfNeeded()
570 if (!m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow)
573 // If the plugin didn't load sucessfully, no point in calling setwindow
574 if (m_status != PluginStatusLoadedSuccessfully)
577 // On Unix, only call plugin if it's full-page or windowed
578 if (m_mode != NP_FULL && m_mode != NP_EMBED)
581 // Check if the platformPluginWidget still exists
582 if (m_isWindowed && !platformPluginWidget())
585 if (!m_hasPendingGeometryChange)
587 m_hasPendingGeometryChange = false;
590 platformPluginWidget()->setGeometry(m_windowRect);
591 // if setMask is set with an empty QRegion, no clipping will
592 // be performed, so in that case we hide the plugin view
593 platformPluginWidget()->setVisible(!m_clipRect.isEmpty());
594 platformPluginWidget()->setMask(QRegion(m_clipRect));
596 m_npWindow.x = m_windowRect.x();
597 m_npWindow.y = m_windowRect.y();
603 // If the width or height are null, set the clipRect to null, indicating that
604 // the plugin is not visible/scrolled out.
605 if (!m_clipRect.width() || !m_clipRect.height()) {
606 m_npWindow.clipRect.left = 0;
607 m_npWindow.clipRect.right = 0;
608 m_npWindow.clipRect.top = 0;
609 m_npWindow.clipRect.bottom = 0;
611 // Clipping rectangle of the plug-in; the origin is the top left corner of the drawable or window.
612 m_npWindow.clipRect.left = m_npWindow.x + m_clipRect.x();
613 m_npWindow.clipRect.top = m_npWindow.y + m_clipRect.y();
614 m_npWindow.clipRect.right = m_npWindow.x + m_clipRect.x() + m_clipRect.width();
615 m_npWindow.clipRect.bottom = m_npWindow.y + m_clipRect.y() + m_clipRect.height();
618 if (m_plugin->quirks().contains(PluginQuirkDontCallSetWindowMoreThanOnce)) {
619 // FLASH WORKAROUND: Only set initially. Multiple calls to
620 // setNPWindow() cause the plugin to crash in windowed mode.
621 if (!m_isWindowed || m_npWindow.width == -1 || m_npWindow.height == -1) {
622 m_npWindow.width = m_windowRect.width();
623 m_npWindow.height = m_windowRect.height();
626 m_npWindow.width = m_windowRect.width();
627 m_npWindow.height = m_windowRect.height();
630 PluginView::setCurrentPluginView(this);
632 JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
634 setCallingPlugin(true);
635 m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
636 setCallingPlugin(false);
637 PluginView::setCurrentPluginView(0);
640 void PluginView::setParentVisible(bool visible)
642 if (isParentVisible() == visible)
645 Widget::setParentVisible(visible);
647 if (isSelfVisible() && platformPluginWidget())
648 platformPluginWidget()->setVisible(visible);
651 NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf)
653 String filename(buf, len);
655 if (filename.startsWith("file:///"))
656 filename = filename.substring(8);
659 if (!getFileSize(filename, size))
660 return NPERR_FILE_NOT_FOUND;
662 FILE* fileHandle = fopen((filename.utf8()).data(), "r");
664 return NPERR_FILE_NOT_FOUND;
667 int bytesRead = fread(buffer.data(), 1, size, fileHandle);
672 return NPERR_FILE_NOT_FOUND;
674 return NPERR_NO_ERROR;
677 bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPError* result)
681 *static_cast<uint32_t*>(value) = 0;
682 *result = NPERR_NO_ERROR;
685 case NPNVSupportsXEmbedBool:
686 *static_cast<NPBool*>(value) = true;
687 *result = NPERR_NO_ERROR;
690 case NPNVjavascriptEnabledBool:
691 *static_cast<NPBool*>(value) = true;
692 *result = NPERR_NO_ERROR;
695 case NPNVSupportsWindowless:
696 *static_cast<NPBool*>(value) = true;
697 *result = NPERR_NO_ERROR;
700 #if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5)
701 case NPNVSupportsWindowlessLocal:
702 *static_cast<NPBool*>(value) = true;
703 *result = NPERR_NO_ERROR;
712 bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result)
716 *(void **)value = QX11Info::display();
717 *result = NPERR_NO_ERROR;
720 case NPNVxtAppContext:
721 *result = NPERR_GENERIC_ERROR;
724 case NPNVnetscapeWindow: {
725 void* w = reinterpret_cast<void*>(value);
726 QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
727 *((XID *)w) = client ? client->ownerWidget()->window()->winId() : 0;
728 *result = NPERR_NO_ERROR;
733 if (m_plugin->quirks().contains(PluginQuirkRequiresGtkToolKit)) {
734 *((uint32_t *)value) = 2;
735 *result = NPERR_NO_ERROR;
745 void PluginView::invalidateRect(const IntRect& rect)
748 if (platformWidget())
749 platformWidget()->update(rect);
753 invalidateWindowlessPluginRect(rect);
756 void PluginView::invalidateRect(NPRect* rect)
762 IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top);
763 invalidateWindowlessPluginRect(r);
766 void PluginView::invalidateRegion(NPRegion region)
771 void PluginView::forceRedraw()
776 static Display *getPluginDisplay()
778 // The plugin toolkit might run using a different X connection. At the moment, we only
779 // support gdk based plugins (like flash) that use a different X connection.
780 // The code below has the same effect as this one:
781 // Display *gdkDisplay = gdk_x11_display_get_xdisplay(gdk_display_get_default());
782 QLibrary library("libgdk-x11-2.0", 0);
786 typedef void *(*gdk_display_get_default_ptr)();
787 gdk_display_get_default_ptr gdk_display_get_default = (gdk_display_get_default_ptr)library.resolve("gdk_display_get_default");
788 if (!gdk_display_get_default)
791 typedef void *(*gdk_x11_display_get_xdisplay_ptr)(void *);
792 gdk_x11_display_get_xdisplay_ptr gdk_x11_display_get_xdisplay = (gdk_x11_display_get_xdisplay_ptr)library.resolve("gdk_x11_display_get_xdisplay");
793 if (!gdk_x11_display_get_xdisplay)
796 return (Display*)gdk_x11_display_get_xdisplay(gdk_display_get_default());
799 static void getVisualAndColormap(int depth, Visual **visual, Colormap *colormap)
804 #ifndef QT_NO_XRENDER
805 static const bool useXRender = qgetenv("QT_X11_NO_XRENDER").isNull(); // Should also check for XRender >= 0.5
807 static const bool useXRender = false;
810 if (!useXRender && depth == 32)
815 templ.screen = QX11Info::appScreen();
817 templ.c_class = TrueColor;
818 XVisualInfo* xvi = XGetVisualInfo(QX11Info::display(), VisualScreenMask | VisualDepthMask | VisualClassMask, &templ, &nvi);
823 #ifndef QT_NO_XRENDER
825 for (int idx = 0; idx < nvi; ++idx) {
826 XRenderPictFormat* format = XRenderFindVisualFormat(QX11Info::display(), xvi[idx].visual);
827 if (format->type == PictTypeDirect && format->direct.alphaMask) {
828 *visual = xvi[idx].visual;
833 #endif // QT_NO_XRENDER
834 *visual = xvi[0].visual;
839 *colormap = XCreateColormap(QX11Info::display(), QX11Info::appRootWindow(), *visual, AllocNone);
842 bool PluginView::platformStart()
845 ASSERT(m_status == PluginStatusLoadedSuccessfully);
847 if (m_plugin->pluginFuncs()->getvalue) {
848 PluginView::setCurrentPluginView(this);
850 JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly);
852 setCallingPlugin(true);
853 m_plugin->pluginFuncs()->getvalue(m_instance, NPPVpluginNeedsXEmbed, &m_needsXEmbed);
854 setCallingPlugin(false);
855 PluginView::setCurrentPluginView(0);
859 QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
860 if (m_needsXEmbed && client) {
861 setPlatformWidget(new PluginContainerQt(this, client->ownerWidget()));
862 // sync our XEmbed container window creation before sending the xid to plugins.
863 QApplication::syncX();
866 m_status = PluginStatusCanNotLoadPlugin;
870 setPlatformWidget(0);
871 m_pluginDisplay = getPluginDisplay();
876 NPSetWindowCallbackStruct* wsi = new NPSetWindowCallbackStruct();
880 const QX11Info* x11Info = &platformPluginWidget()->x11Info();
882 wsi->display = x11Info->display();
883 wsi->visual = (Visual*)x11Info->visual();
884 wsi->depth = x11Info->depth();
885 wsi->colormap = x11Info->colormap();
887 m_npWindow.type = NPWindowTypeWindow;
888 m_npWindow.window = (void*)platformPluginWidget()->winId();
889 m_npWindow.width = -1;
890 m_npWindow.height = -1;
892 const QX11Info* x11Info = &QApplication::desktop()->x11Info();
894 if (x11Info->depth() == 32 || !m_plugin->quirks().contains(PluginQuirkRequiresDefaultScreenDepth)) {
895 getVisualAndColormap(32, &m_visual, &m_colormap);
900 getVisualAndColormap(x11Info->depth(), &m_visual, &m_colormap);
901 wsi->depth = x11Info->depth();
904 wsi->display = x11Info->display();
905 wsi->visual = m_visual;
906 wsi->colormap = m_colormap;
908 m_npWindow.type = NPWindowTypeDrawable;
909 m_npWindow.window = 0; // Not used?
912 m_npWindow.width = -1;
913 m_npWindow.height = -1;
916 m_npWindow.ws_info = wsi;
918 if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall))) {
919 updatePluginWidget();
920 setNPWindowIfNeeded();
926 void PluginView::platformDestroy()
928 if (platformPluginWidget())
929 delete platformPluginWidget();
932 XFreePixmap(QX11Info::display(), m_drawable);
935 XFreeColormap(QX11Info::display(), m_colormap);
938 void PluginView::halt()
942 void PluginView::restart()
946 } // namespace WebCore