| /* |
| * Copyright 2009, The Android Open Source Project |
| * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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. |
| */ |
| |
| #define LOG_TAG "WebCore" |
| |
| #include "config.h" |
| #include "PluginView.h" |
| |
| #include "Document.h" |
| #include "Element.h" |
| #include "EventNames.h" |
| #include "FocusController.h" |
| #include "FrameLoader.h" |
| #include "FrameLoadRequest.h" |
| #include "FrameTree.h" |
| #include "Frame.h" |
| #include "FrameView.h" |
| #include "GraphicsContext.h" |
| #include "HTMLNames.h" |
| #include "HTMLPlugInElement.h" |
| #include "Image.h" |
| #include "KeyboardEvent.h" |
| #include "MIMETypeRegistry.h" |
| #include "MouseEvent.h" |
| #include "NetworkStateNotifier.h" |
| #include "NotImplemented.h" |
| #include "Page.h" |
| #include "PlatformGraphicsContext.h" |
| #include "PlatformKeyboardEvent.h" |
| #include "PluginMainThreadScheduler.h" |
| #include "PluginPackage.h" |
| #include "Touch.h" |
| #include "TouchEvent.h" |
| #include "TouchList.h" |
| #include "SkCanvas.h" |
| #include "npruntime_impl.h" |
| // #include "runtime_root.h" |
| #include "utils/SystemClock.h" |
| #include "ScriptController.h" |
| #include "Settings.h" |
| |
| #include <wtf/ASCIICType.h> |
| // #include "runtime.h" |
| #include "WebViewCore.h" |
| |
| /* Controls the printing of log messages in this file. This must be defined |
| before PluginDebugAndroid.h is included. |
| */ |
| // #define PLUGIN_DEBUG_LOCAL |
| #define TRACE_KEY_EVENTS 0 |
| |
| #include "PluginDebug.h" |
| #include "PluginDebugAndroid.h" |
| #include "PluginViewBridgeAndroid.h" |
| #include "PluginWidgetAndroid.h" |
| |
| #include "android_npapi.h" |
| #include "ANPNativeWindow_npapi.h" |
| #include "ANPSurface_npapi.h" |
| #include "ANPSystem_npapi.h" |
| #include "ANPVideo_npapi.h" |
| #include "SkANP.h" |
| #include "SkFlipPixelRef.h" |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| extern void ANPAudioTrackInterfaceV0_Init(ANPInterface* value); |
| extern void ANPAudioTrackInterfaceV1_Init(ANPInterface* value); |
| extern void ANPBitmapInterfaceV0_Init(ANPInterface* value); |
| extern void ANPCanvasInterfaceV0_Init(ANPInterface* value); |
| extern void ANPEventInterfaceV0_Init(ANPInterface* value); |
| extern void ANPLogInterfaceV0_Init(ANPInterface* value); |
| extern void ANPMatrixInterfaceV0_Init(ANPInterface* value); |
| extern void ANPOffscreenInterfaceV0_Init(ANPInterface* value); |
| extern void ANPPaintInterfaceV0_Init(ANPInterface* value); |
| extern void ANPPathInterfaceV0_Init(ANPInterface* value); |
| extern void ANPSurfaceInterfaceV0_Init(ANPInterface* value); |
| extern void ANPTypefaceInterfaceV0_Init(ANPInterface* value); |
| extern void ANPWindowInterfaceV0_Init(ANPInterface* value); |
| extern void ANPWindowInterfaceV1_Init(ANPInterface* value); |
| extern void ANPWindowInterfaceV2_Init(ANPInterface* value); |
| extern void ANPSystemInterfaceV0_Init(ANPInterface* value); |
| extern void ANPSystemInterfaceV1_Init(ANPInterface* value); |
| extern void ANPSystemInterfaceV2_Init(ANPInterface* value); |
| extern void ANPNativeWindowInterfaceV0_Init(ANPInterface* value); |
| extern void ANPVideoInterfaceV0_Init(ANPInterface* value); |
| extern void ANPVideoInterfaceV1_Init(ANPInterface* value); |
| |
| struct VarProcPair { |
| int enumValue; |
| size_t size; |
| void (*proc)(ANPInterface*); |
| }; |
| |
| #define VARPROCLINE(name) \ |
| k##name##_ANPGetValue, sizeof(ANP##name), ANP##name##_Init |
| |
| static const VarProcPair gVarProcs[] = { |
| { VARPROCLINE(AudioTrackInterfaceV0) }, |
| { VARPROCLINE(AudioTrackInterfaceV1) }, |
| { VARPROCLINE(BitmapInterfaceV0) }, |
| { VARPROCLINE(CanvasInterfaceV0) }, |
| { VARPROCLINE(EventInterfaceV0) }, |
| { VARPROCLINE(LogInterfaceV0) }, |
| { VARPROCLINE(MatrixInterfaceV0) }, |
| { VARPROCLINE(PaintInterfaceV0) }, |
| { VARPROCLINE(PathInterfaceV0) }, |
| { VARPROCLINE(SurfaceInterfaceV0) }, |
| { VARPROCLINE(TypefaceInterfaceV0) }, |
| { VARPROCLINE(WindowInterfaceV0) }, |
| { VARPROCLINE(WindowInterfaceV1) }, |
| { VARPROCLINE(WindowInterfaceV2) }, |
| { VARPROCLINE(SystemInterfaceV0) }, |
| { VARPROCLINE(SystemInterfaceV1) }, |
| { VARPROCLINE(SystemInterfaceV2) }, |
| { VARPROCLINE(NativeWindowInterfaceV0) }, |
| { VARPROCLINE(VideoInterfaceV0) }, |
| { VARPROCLINE(VideoInterfaceV1) }, |
| }; |
| |
| /* return true if var was an interface request (error will be set accordingly) |
| return false if var is not a recognized interface (and ignore error param) |
| */ |
| static bool anp_getInterface(NPNVariable var, void* value, NPError* error) { |
| const VarProcPair* iter = gVarProcs; |
| const VarProcPair* stop = gVarProcs + SK_ARRAY_COUNT(gVarProcs); |
| while (iter < stop) { |
| if (iter->enumValue == var) { |
| ANPInterface* i = reinterpret_cast<ANPInterface*>(value); |
| if (i->inSize < iter->size) { |
| SkDebugf("------- interface %d, expected size %d, allocated %d\n", |
| var, iter->size, i->inSize); |
| *error = NPERR_INCOMPATIBLE_VERSION_ERROR; |
| } else { |
| iter->proc(i); |
| *error = NPERR_NO_ERROR; |
| } |
| return true; |
| } |
| iter += 1; |
| } |
| SkDebugf("------ unknown NPNVariable %d\n", var); |
| return false; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| using std::min; |
| |
| using namespace WTF; |
| |
| namespace WebCore { |
| |
| using namespace HTMLNames; |
| |
| void PluginView::platformInit() |
| { |
| setPlatformWidget(new PluginViewBridgeAndroid()); |
| |
| m_isWindowed = false; // we don't support windowed yet |
| |
| m_window = new PluginWidgetAndroid(this); |
| |
| m_npWindow.type = NPWindowTypeDrawable; |
| m_npWindow.window = 0; |
| } |
| |
| bool PluginView::platformStart() |
| { |
| return true; |
| } |
| |
| void PluginView::platformDestroy() |
| { |
| delete m_window; |
| } |
| |
| PlatformLayer* PluginView::platformLayer() const |
| { |
| return (PlatformLayer*) m_window->getLayer(); |
| } |
| |
| #if ENABLE(TOUCH_EVENTS) |
| void PluginView::handleTouchEvent(TouchEvent* event) |
| { |
| if (!m_window->isAcceptingEvent(kTouch_ANPEventFlag)) |
| return; |
| |
| if (!m_window->inFullScreen() && m_parentFrame->document()->focusedNode() != m_element) |
| return; |
| |
| ANPEvent evt; |
| SkANP::InitEvent(&evt, kMultiTouch_ANPEventType); |
| |
| const AtomicString& type = event->type(); |
| if (eventNames().touchstartEvent == type) |
| evt.data.multiTouch.action = kDown_ANPTouchAction; |
| else if (eventNames().touchendEvent == type) |
| evt.data.multiTouch.action = kUp_ANPTouchAction; |
| else if (eventNames().touchmoveEvent == type) |
| evt.data.multiTouch.action = kMove_ANPTouchAction; |
| else if (eventNames().touchcancelEvent == type) |
| evt.data.multiTouch.action = kCancel_ANPTouchAction; |
| else if (eventNames().touchlongpressEvent == type) |
| evt.data.multiTouch.action = kLongPress_ANPTouchAction; |
| else if (eventNames().touchdoubletapEvent == type) |
| evt.data.multiTouch.action = kDoubleTap_ANPTouchAction; |
| else |
| return; |
| |
| // set the id and timestamp |
| evt.data.multiTouch.id = 0; // TODO |
| evt.data.multiTouch.timestamp = 0; // TODO |
| |
| // In the event of a touchend (up) or touchcancel event, we must ask the changedTouch for the |
| // co-ordinates as there is no touch in touches anymore. |
| TouchList* touches = (evt.data.multiTouch.action == kUp_ANPTouchAction |
| || evt.data.multiTouch.action == kCancel_ANPTouchAction) ? event->changedTouches() : event->touches(); |
| |
| // set each touchPoint |
| int pointerCount = touches->length(); |
| evt.data.multiTouch.pointerCount = pointerCount; |
| evt.data.multiTouch.touchPoint = new TouchPoint[pointerCount]; |
| |
| for (int x = 0; x < evt.data.multiTouch.pointerCount; x++) { |
| Touch* touch = touches->item(x); |
| // Convert to coordinates that are relative to the plugin. |
| IntPoint localPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(IntPoint(touch->pageX(), touch->pageY()))); |
| |
| evt.data.multiTouch.touchPoint[x].id = touch->identifier(); |
| evt.data.multiTouch.touchPoint[x].x = localPos.x(); |
| evt.data.multiTouch.touchPoint[x].y = localPos.y(); |
| evt.data.multiTouch.touchPoint[x].pressure = 1; // TODO |
| evt.data.multiTouch.touchPoint[x].size = 1; // TODO |
| } |
| |
| if (m_window->sendEvent(evt)) |
| event->preventDefault(); |
| |
| // cleanup the touch points we allocated |
| delete[] evt.data.multiTouch.touchPoint; |
| } |
| #endif |
| |
| void PluginView::handleMouseEvent(MouseEvent* event) |
| { |
| const AtomicString& type = event->type(); |
| bool isUp = (eventNames().mouseupEvent == type); |
| bool isDown = (eventNames().mousedownEvent == type); |
| |
| ANPEvent evt; |
| |
| if (isUp || isDown) { |
| SkANP::InitEvent(&evt, kMouse_ANPEventType); |
| evt.data.mouse.action = isUp ? kUp_ANPMouseAction : kDown_ANPMouseAction; |
| |
| // Convert to coordinates that are relative to the plugin. |
| IntPoint localPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation())); |
| evt.data.mouse.x = localPos.x(); |
| evt.data.mouse.y = localPos.y(); |
| |
| if (isDown) { |
| // The plugin needs focus to receive keyboard and touch events |
| m_element->focus(); |
| event->setDefaultHandled(); |
| } |
| } |
| else { |
| return; |
| } |
| |
| if (m_window->sendEvent(evt)) { |
| event->setDefaultHandled(); |
| } |
| } |
| |
| static ANPKeyModifier make_modifiers(bool shift, bool alt) { |
| ANPKeyModifier mod = 0; |
| if (shift) { |
| mod |= kShift_ANPKeyModifier; |
| } |
| if (alt) { |
| mod |= kAlt_ANPKeyModifier; |
| } |
| return mod; |
| } |
| |
| void PluginView::handleFocusEvent(bool hasFocus) |
| { |
| ANPEvent evt; |
| SkANP::InitEvent(&evt, kLifecycle_ANPEventType); |
| evt.data.lifecycle.action = hasFocus ? kGainFocus_ANPLifecycleAction : |
| kLoseFocus_ANPLifecycleAction; |
| m_window->sendEvent(evt); |
| |
| // redraw the plugin which subsequently invalidates the nav cache |
| IntRect rect = IntRect(m_npWindow.x, m_npWindow.y, |
| m_npWindow.width, m_npWindow.height); |
| m_window->webViewCore()->contentInvalidate(rect); |
| } |
| |
| void PluginView::handleKeyboardEvent(KeyboardEvent* event) |
| { |
| if (!m_window->isAcceptingEvent(kKey_ANPEventFlag)) |
| return; |
| |
| const PlatformKeyboardEvent* pke = event->keyEvent(); |
| if (NULL == pke) { |
| return; |
| } |
| |
| bool ignoreEvent = false; |
| |
| ANPEvent evt; |
| SkANP::InitEvent(&evt, kKey_ANPEventType); |
| |
| switch (pke->type()) { |
| case PlatformKeyboardEvent::KeyDown: |
| #if TRACE_KEY_EVENTS |
| PLUGIN_LOG("--------- KeyDown, ignore\n"); |
| #endif |
| ignoreEvent = true; |
| break; |
| case PlatformKeyboardEvent::RawKeyDown: |
| evt.data.key.action = kDown_ANPKeyAction; |
| break; |
| case PlatformKeyboardEvent::Char: |
| #if TRACE_KEY_EVENTS |
| PLUGIN_LOG("--------- Char, ignore\n"); |
| #endif |
| ignoreEvent = true; |
| break; |
| case PlatformKeyboardEvent::KeyUp: |
| evt.data.key.action = kUp_ANPKeyAction; |
| break; |
| default: |
| #if TRACE_KEY_EVENTS |
| PLUGIN_LOG("------ unexpected keyevent type %d\n", pke->type()); |
| #endif |
| ignoreEvent = true; |
| break; |
| } |
| |
| /* the plugin should be the only party able to return nav control to the |
| * browser UI. Therefore, if we discard an event on behalf of the plugin |
| * we should mark the event as being handled. |
| */ |
| if (ignoreEvent) { |
| int keyCode = pke->nativeVirtualKeyCode(); |
| if (keyCode >= kDpadUp_ANPKeyCode && keyCode <= kDpadCenter_ANPKeyCode) |
| event->setDefaultHandled(); |
| return; |
| } |
| |
| evt.data.key.nativeCode = pke->nativeVirtualKeyCode(); |
| evt.data.key.virtualCode = pke->windowsVirtualKeyCode(); |
| evt.data.key.repeatCount = pke->repeatCount(); |
| evt.data.key.modifiers = make_modifiers(pke->shiftKey(), pke->altKey()); |
| evt.data.key.unichar = pke->unichar(); |
| |
| if (m_window->sendEvent(evt)) { |
| event->setDefaultHandled(); |
| } else if (m_window->inFullScreen()){ |
| // while in the full screen mode, always consumes the key events and |
| // keeps the document focus |
| event->setDefaultHandled(); |
| } else { |
| // remove the plugin from the document's focus |
| m_parentFrame->document()->focusedNodeRemoved(); |
| } |
| } |
| |
| NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf) |
| { |
| notImplemented(); |
| return NPERR_GENERIC_ERROR; |
| } |
| |
| bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPError* result) |
| { |
| // our interface query is valid with no NPP instance |
| *result = NPERR_GENERIC_ERROR; |
| |
| switch ((int)variable) { |
| case NPNVisOfflineBool: { |
| if (value != NULL) { |
| bool* retValue = static_cast<bool*>(value); |
| *retValue = !networkStateNotifier().onLine(); |
| *result = NPERR_NO_ERROR; |
| return true; |
| } |
| break; |
| } |
| case kJavaContext_ANPGetValue: { |
| jobject* retObject = static_cast<jobject*>(value); |
| *retObject = android::WebViewCore::getApplicationContext(); |
| *result = NPERR_NO_ERROR; |
| return true; |
| } |
| default: |
| break; // do nothing |
| } |
| |
| (void)anp_getInterface(variable, value, result); |
| return true; |
| } |
| |
| void PluginView::setParent(ScrollView* parent) |
| { |
| PLUGIN_LOG("--%p SetParent old=[%p], new=[%p] \n", instance(), this->parent(), parent); |
| |
| Widget::setParent(parent); |
| |
| if (parent) { |
| // the widget needs initialized now so that the plugin has access to |
| // WebViewCore when NPP_New is called |
| if (m_window && !m_window->webViewCore()) { |
| android::WebViewCore* c = android::WebViewCore::getWebViewCore(this->parent()); |
| m_window->init(c); |
| } |
| init(); |
| |
| /* Our widget needs to recompute its m_windowRect which then sets |
| the NPWindowRect if necessary. This ensures that if NPWindowRect |
| is set prior to parent() being set that we still (1) notify the |
| plugin of its current rect and (2) that we execute our logic in |
| PluginWidgetAndroid in response to changes to NPWindowRect. |
| */ |
| updatePluginWidget(); |
| } |
| } |
| |
| void PluginView::setNPWindowRect(const IntRect&) |
| { |
| setNPWindowIfNeeded(); |
| } |
| |
| void PluginView::setNPWindowIfNeeded() |
| { |
| PLUGIN_LOG("--%p SetWindow isStarted=[%d] \n", instance(), m_isStarted); |
| |
| if (!m_isStarted || !parent()) |
| return; |
| |
| // in Android, plugin always get the setwindow() in the page coordinate. |
| |
| // the m_npWindow is relative to the page |
| m_npWindow.x = m_pageRect.x(); |
| m_npWindow.y = m_pageRect.y(); |
| m_npWindow.width = m_pageRect.width(); |
| m_npWindow.height = m_pageRect.height(); |
| |
| m_npWindow.clipRect.left = m_pageRect.x(); |
| m_npWindow.clipRect.top = m_pageRect.y(); |
| m_npWindow.clipRect.right = m_pageRect.x() + m_pageRect.width(); |
| m_npWindow.clipRect.bottom = m_pageRect.y() + m_pageRect.height(); |
| |
| if (m_plugin->pluginFuncs()->setwindow) { |
| setCallingPlugin(true); |
| m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow); |
| setCallingPlugin(false); |
| } |
| |
| m_window->setWindow(&m_npWindow, m_isTransparent); |
| } |
| |
| bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result) |
| { |
| switch ((int)variable) { |
| case NPNVWindowNPObject: { |
| NPObject* windowScriptObject = |
| m_parentFrame->script()->windowScriptNPObject(); |
| |
| // Return value is expected to be retained, as described |
| // here: |
| // <http://www.mozilla.org/projects/plugin/npruntime.html> |
| if (windowScriptObject) |
| _NPN_RetainObject(windowScriptObject); |
| |
| void** v = (void**)value; |
| *v = windowScriptObject; |
| |
| *result = NPERR_NO_ERROR; |
| return true; |
| } |
| |
| case NPNVPluginElementNPObject: { |
| NPObject* pluginScriptObject = 0; |
| |
| if (m_element->hasTagName(appletTag) || |
| m_element->hasTagName(embedTag) || |
| m_element->hasTagName(objectTag)) { |
| HTMLPlugInElement* pluginElement = |
| static_cast<HTMLPlugInElement*>(m_element); |
| pluginScriptObject = pluginElement->getNPObject(); |
| } |
| |
| // Return value is expected to be retained, as described |
| // here: |
| // <http://www.mozilla.org/projects/plugin/npruntime.html> |
| if (pluginScriptObject) |
| _NPN_RetainObject(pluginScriptObject); |
| |
| void** v = (void**)value; |
| *v = pluginScriptObject; |
| |
| *result = NPERR_NO_ERROR; |
| return true; |
| } |
| |
| case NPNVnetscapeWindow: { |
| // Return the top level WebView Java object associated |
| // with this instance. |
| jobject *retObject = static_cast<jobject*>(value); |
| // TODO: Is it safe for this to be NULL? It looks from the NPNVWindowNPObject case that it is. |
| *retObject = android::WebViewCore::getWebViewCore(parent())->getWebViewJavaObject(); |
| *result = NPERR_NO_ERROR; |
| return true; |
| } |
| |
| case NPNVisOfflineBool: { |
| if (value == NULL) { |
| *result = NPERR_GENERIC_ERROR; |
| return true; |
| } |
| bool* retValue = static_cast<bool*>(value); |
| *retValue = !networkStateNotifier().onLine(); |
| *result = NPERR_NO_ERROR; |
| return true; |
| } |
| |
| case kSupportedDrawingModel_ANPGetValue: { |
| uint32_t* bits = reinterpret_cast<uint32_t*>(value); |
| *bits = kBitmap_ANPDrawingModel & kSurface_ANPDrawingModel; |
| *result = NPERR_NO_ERROR; |
| return true; |
| } |
| |
| case kJavaContext_ANPGetValue: { |
| jobject* retObject = static_cast<jobject*>(value); |
| // TODO: Is it safe for this to be NULL? It looks from the NPNVWindowNPObject case that it is. |
| *retObject = android::WebViewCore::getWebViewCore(parent())->getContext(); |
| *result = NPERR_NO_ERROR; |
| return true; |
| } |
| |
| default: { |
| NPError error = NPERR_GENERIC_ERROR; |
| (void)anp_getInterface(variable, value, &error); |
| *result = error; |
| return true; |
| } |
| } |
| } |
| |
| NPError PluginView::platformSetValue(NPPVariable variable, void* value) |
| { |
| NPError error = NPERR_GENERIC_ERROR; |
| |
| switch ((int)variable) { |
| case kRequestDrawingModel_ANPSetValue: { |
| ANPDrawingModel model = reinterpret_cast<ANPDrawingModel>(value); |
| if (m_window->setDrawingModel(model)) |
| error = NPERR_NO_ERROR; |
| break; |
| } |
| case kAcceptEvents_ANPSetValue : { |
| if(value) { |
| ANPEventFlags flags = *reinterpret_cast<ANPEventFlags*>(value); |
| m_window->updateEventFlags(flags); |
| error = NPERR_NO_ERROR; |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| return error; |
| } |
| |
| void PluginView::invalidateRect(const IntRect& r) |
| { |
| m_window->inval(r, true); |
| } |
| |
| void PluginView::invalidateRect(NPRect* rect) |
| { |
| IntRect r; |
| |
| if (rect) { |
| r = IntRect(rect->left, rect->top, |
| rect->right - rect->left, rect->bottom - rect->top); |
| } else { |
| r = IntRect(0, 0, m_npWindow.width, m_npWindow.height); |
| } |
| |
| m_window->inval(r, true); |
| } |
| |
| void PluginView::invalidateRegion(NPRegion region) |
| { |
| // we don't support/define regions (yet), so do nothing |
| } |
| |
| void PluginView::forceRedraw() |
| { |
| this->invalidateRect(0); |
| } |
| |
| void PluginView::setFocus(bool focused) |
| { |
| Widget::setFocus(focused); |
| // SkDebugf("------------- setFocus %p\n", this); |
| } |
| |
| void PluginView::show() |
| { |
| setSelfVisible(true); |
| Widget::show(); |
| |
| if (platformPluginWidget()) |
| platformPluginWidget()->layoutSurface(); |
| |
| } |
| |
| void PluginView::hide() |
| { |
| setSelfVisible(false); |
| Widget::hide(); |
| |
| if (platformPluginWidget()) |
| platformPluginWidget()->layoutSurface(); |
| } |
| |
| void PluginView::setParentVisible(bool visible) { |
| |
| if (isParentVisible() == visible) |
| return; |
| |
| Widget::setParentVisible(visible); |
| |
| if (platformPluginWidget()) |
| platformPluginWidget()->layoutSurface(); |
| |
| } |
| |
| void PluginView::paint(GraphicsContext* context, const IntRect& rect) |
| { |
| if (!m_isStarted) { |
| // Draw the "missing plugin" image |
| paintMissingPluginIcon(context, rect); |
| return; |
| } |
| |
| IntRect frame = frameRect(); |
| if (!frame.width() || !frame.height()) { |
| PLUGIN_LOG("--%p FrameRect Dimensions are (0,0).\n", instance()); |
| return; |
| } |
| |
| if (m_window->isSurfaceDrawingModel()) { |
| /* the document position of the frame (e.g. iFrame) containing the |
| surface may have changed, which requires us to to update the global |
| coordinates of the surface. This is necessary because the plugin has |
| not moved within its parent frame and therefore will not get any |
| notification of its global position change. |
| */ |
| updatePluginWidget(); |
| m_window->setSurfaceClip(context->platformContext()->getTotalClipBounds()); |
| } else { |
| m_window->inval(rect, false); |
| context->save(); |
| context->translate(frame.x(), frame.y()); |
| m_window->draw(context->platformContext()); |
| context->restore(); |
| } |
| |
| |
| } |
| |
| void PluginView::updatePluginWidget() |
| { |
| FrameView* frameView = static_cast<FrameView*>(parent()); |
| PLUGIN_LOG("--%p UpdatePluginWidget frame=[%p] \n", instance(), frameView); |
| if (frameView) { |
| m_windowRect = frameView->contentsToWindow(frameRect()); |
| |
| IntRect oldPageRect = m_pageRect; |
| |
| // only the top ScrollView can have the offset |
| m_pageRect = m_windowRect; |
| ScrollView* top = parent(); |
| while (top->parent()) |
| top = top->parent(); |
| m_pageRect.move(top->scrollOffset()); |
| |
| if (m_pageRect != oldPageRect) |
| setNPWindowIfNeeded(); |
| } |
| } |
| |
| void PluginView::halt() { |
| notImplemented(); |
| } |
| |
| void PluginView::restart() { |
| notImplemented(); |
| } |
| |
| } // namespace WebCore |