⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 render_frames.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            if (!root->minMaxKnown())
                root->calcMinMaxWidth();

            // if no scrolling for this frame, minwidth is set to zero
            if (element()->scrollingMode() != QScrollView::AlwaysOff
                || (body && body->id()==ID_FRAMESET) )
                m_minWidth = QMAX(root->minWidth(),root->docWidth());
            m_maxWidth = QMAX(root->maxWidth(),m_minWidth);
        }
    }

    setMinMaxKnown();

#ifdef DEBUG_LAYOUT
    kdDebug( 6040 ) << "RenderFrame::calcMinMaxWidth(" << this << "): min = " << m_minWidth << " max = " << m_maxWidth << endl;
#endif
}

void RenderFrame::layout()
{
    // expand the frame by setting frame height = content height
#ifdef DEBUG_LAYOUT
    kdDebug( 6040 ) << renderName() << "(RenderFrame)::layout() this=" << this << endl;
#endif

    m_width = QMAX(m_width,m_minWidth);

    QScrollView* sview = static_cast<QScrollView *>(m_widget);
    if (sview && sview->inherits("KHTMLView")) {
        KHTMLView* view = static_cast<KHTMLView *>(sview);
        RenderCanvas* root = static_cast<RenderCanvas*>(view->part()?(view->part()->xmlDocImpl()?view->part()->xmlDocImpl()->renderer():0):0);
        if (root) {
            NodeImpl *body = 0;
            if (view->part()->xmlDocImpl()->isHTMLDocument())
                body = static_cast<HTMLDocumentImpl *>(view->part()->xmlDocImpl())->body();
            if (root->needsLayout())
                root->layout();
            if (element()->scrollingMode() != QScrollView::AlwaysOff
                || (body && body->id()==ID_FRAMESET) )
                m_height = QMAX(m_height,root->docHeight());
        }
    }

//    kdDebug( 0 ) << "m_height =" << m_height << endl;

    setNeedsLayout(false);

}
#endif

/****************************************************************************************/

RenderPartObject::RenderPartObject( DOM::HTMLElementImpl* element )
    : RenderPart( element )
{
    // init RenderObject attributes
    setInline(true);
}

void RenderPartObject::updateWidget()
{
  QString url;
  QString serviceType;
  QStringList paramNames;
  QStringList paramValues;
  KHTMLPart *part = m_view->part();

  setNeedsLayoutAndMinMaxRecalc();

  if (element()->id() == ID_OBJECT) {

      HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element());

      // Check for a child EMBED tag.
      HTMLEmbedElementImpl *embed = 0;
      for (NodeImpl *child = o->firstChild(); child; ) {
          if (child->id() == ID_EMBED) {
              embed = static_cast<HTMLEmbedElementImpl *>( child );
              break;
          } else if (child->id() == ID_OBJECT) {
              child = child->nextSibling();         // Don't descend into nested OBJECT tags
          } else {
              child = child->traverseNextNode(o);   // Otherwise descend (EMBEDs may be inside COMMENT tags)
          }
      }

      // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT.
      HTMLElementImpl *embedOrObject;
      if (embed) {
          embedOrObject = (HTMLElementImpl *)embed;
          DOMString attribute = embedOrObject->getAttribute(ATTR_WIDTH);
          if (!attribute.isEmpty()) {
              o->setAttribute(ATTR_WIDTH, attribute);
          }
          attribute = embedOrObject->getAttribute(ATTR_HEIGHT);
          if (!attribute.isEmpty()) {
              o->setAttribute(ATTR_HEIGHT, attribute);
          }
          url = embed->url;
          serviceType = embed->serviceType;
      } else {
          embedOrObject = (HTMLElementImpl *)o;
      }

      // If there was no URL or type defined in EMBED, try the OBJECT tag.
      if (url.isEmpty()) {
          url = o->url;
      }
      if (serviceType.isEmpty()) {
          serviceType = o->serviceType;
      }

      QDict<bool> uniqueParamNames(5, false);

      // Scan the PARAM children.
      // Get the URL and type from the params if we don't already have them.
      // Get the attributes from the params if there is no EMBED tag.
      NodeImpl *child = o->firstChild();
      while (child && (url.isEmpty() || serviceType.isEmpty() || !embed)) {
          if (child->id() == ID_PARAM) {
              HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>( child );
              QString name = p->name().lower();
              if (url.isEmpty() && (name == "src" || name == "movie" || name == "code" || name == "url")) {
                  url = p->value();
              }
              if (serviceType.isEmpty() && name == "type") {
                  serviceType = p->value();
                  int pos = serviceType.find( ";" );
                  if (pos != -1) {
                      serviceType = serviceType.left(pos);
                  }
              }
              if (!embed) {
                  bool dummyValue = true;
                  uniqueParamNames.insert(p->name(), &dummyValue);
                  paramNames.append(p->name());
                  paramValues.append(p->value());
              }
          }
          child = child->nextSibling();
      }

      // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE attribute in the tag
      // points to the Java plugin itself (an ActiveX component) while the actual applet CODEBASE is
      // in a PARAM tag. See <http://java.sun.com/products/plugin/1.2/docs/tags.html>. This means
      // we have to explicitly suppress the tag's CODEBASE attribute if there is none in a PARAM,
      // else our Java plugin will misinterpret it. [4004531]
      if (!embed && serviceType.lower() == "application/x-java-applet") {
          bool dummyValue = true;
          uniqueParamNames.insert("codebase", &dummyValue); // pretend we found it in a PARAM already
      }

      // Turn the attributes of either the EMBED tag or OBJECT tag into arrays, but don't override PARAM values.
      NamedAttrMapImpl* attributes = embedOrObject->attributes();
      if (attributes) {
          for (unsigned long i = 0; i < attributes->length(); ++i) {
              AttributeImpl* it = attributes->attributeItem(i);
              QString name = o->getDocument()->attrName(it->id()).string();
              if (embed || uniqueParamNames.find(name) == 0) {
                  paramNames.append(name);
                  paramValues.append(it->value().string());
              }
          }
      }

      // If we still don't have a type, try to map from a specific CLASSID to a type.
      if (serviceType.isEmpty() && !o->classId.isEmpty()) {
          // It is ActiveX, but the nsplugin system handling
          // should also work, that's why we don't override the
          // serviceType with application/x-activex-handler
          // but let the KTrader in khtmlpart::createPart() detect
          // the user's preference: launch with activex viewer or
          // with nspluginviewer (Niko)
          if (o->classId.contains("D27CDB6E-AE6D-11cf-96B8-444553540000")) {
              serviceType = "application/x-shockwave-flash";
          } else if (o->classId.contains("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA")) {
              serviceType = "audio/x-pn-realaudio-plugin";
          } else if (o->classId.contains("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B")) {
              serviceType = "video/quicktime";
          } else if (o->classId.contains("166B1BCA-3F9C-11CF-8075-444553540000")) {
              serviceType = "application/x-director";
          } else if (o->classId.contains("6BF52A52-394A-11d3-B153-00C04F79FAA6")) {
              serviceType = "application/x-mplayer2";
          } else {
              // We have a clsid, means this is activex (Niko)
              serviceType = "application/x-activex-handler";
          }
          // TODO: add more plugins here
      }

      // If no URL and type, abort.
      if (url.isEmpty() && serviceType.isEmpty()) {
#ifdef DEBUG_LAYOUT
          kdDebug() << "RenderPartObject::close - empty url and serverType" << endl;
#endif
          return;
      }
      // Avoid infinite recursion. If the plug-in's URL is the same as the part's URL, infinite frames may be created.
      if (!url.isEmpty() && part->completeURL(url) == part->baseURL()) {
          return;
      }

#if !APPLE_CHANGES
      params.append( QString::fromLatin1("__KHTML__CLASSID=\"%1\"").arg( o->classId ) );
      params.append( QString::fromLatin1("__KHTML__CODEBASE=\"%1\"").arg( o->getAttribute(ATTR_CODEBASE).string() ) );
#endif

      part->requestObject( this, url, serviceType, paramNames, paramValues );
  } else if ( element()->id() == ID_EMBED ) {

      HTMLEmbedElementImpl *o = static_cast<HTMLEmbedElementImpl *>(element());
      url = o->url;
      serviceType = o->serviceType;

      if ( url.isEmpty() && serviceType.isEmpty() ) {
#ifdef DEBUG_LAYOUT
          kdDebug() << "RenderPartObject::close - empty url and serverType" << endl;
#endif
          return;
      }
      // Avoid infinite recursion. If the plug-in's URL is the same as the part's URL, infinite frames may be created.
      if (!url.isEmpty() && part->completeURL(url) == part->baseURL()) {
          return;
      }
      // add all attributes set on the embed object
      NamedAttrMapImpl* a = o->attributes();
      if (a) {
          for (unsigned long i = 0; i < a->length(); ++i) {
              AttributeImpl* it = a->attributeItem(i);
              paramNames.append(o->getDocument()->attrName(it->id()).string());
              paramValues.append(it->value().string());
          }
      }
      part->requestObject( this, url, serviceType, paramNames, paramValues );
  } else {
      assert(element()->id() == ID_IFRAME);
      HTMLIFrameElementImpl *o = static_cast<HTMLIFrameElementImpl *>(element());
      url = o->url.string();
      if (url.isEmpty()) {
      url = "about:blank";
      }
      KHTMLView *v = static_cast<KHTMLView *>(m_view);
      bool requestSucceeded = v->part()->requestFrame( this, url, o->name.string(), QStringList(), QStringList(), true );
      if (requestSucceeded && url == "about:blank") {
      KHTMLPart *newPart = v->part()->findFrame( o->name.string() );
      if (newPart && newPart->xmlDocImpl()) {
          newPart->xmlDocImpl()->setBaseURL( v->part()->baseURL().url() );
      }
      }
  }
}

bool RenderPartObject::partLoadingErrorNotify( khtml::ChildFrame *childFrame, const KURL& url, const QString& serviceType )
{
    KHTMLPart *part = static_cast<KHTMLView *>(m_view)->part();
    //kdDebug() << "RenderPartObject::partLoadingErrorNotify serviceType=" << serviceType << endl;
    // Check if we just tried with e.g. nsplugin
    // and fallback to the activexhandler if there is a classid
    // and a codebase, where we may download the ocx if it's missing
    if( serviceType != "application/x-activex-handler" && element()->id()==ID_OBJECT ) {

        // check for embed child object
        HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element());
        HTMLEmbedElementImpl *embed = 0;
        NodeImpl *child = o->firstChild();
        while ( child ) {
            if ( child->id() == ID_EMBED )
                embed = static_cast<HTMLEmbedElementImpl *>( child );

            child = child->nextSibling();
        }
        if( embed && !o->classId.isEmpty() &&
            !( static_cast<ElementImpl *>(o)->getAttribute(ATTR_CODEBASE).string() ).isEmpty() )
        {
            KParts::URLArgs args;
            args.serviceType = "application/x-activex-handler";
            if (part->requestObject( childFrame, url, args ))
                return true; // success
        }
    }
    // Dissociate ourselves from the current event loop (to prevent crashes
    // due to the message box staying up)
    QTimer::singleShot( 0, this, SLOT( slotPartLoadingErrorNotify() ) );
    Tokenizer *tokenizer = static_cast<DOM::DocumentImpl *>(part->document().handle())->tokenizer();
    if (tokenizer) tokenizer->setOnHold( true );
    slotPartLoadingErrorNotify();
    if (tokenizer) tokenizer->setOnHold( false );
    return false;
}

void RenderPartObject::slotPartLoadingErrorNotify()
{
#if APPLE_CHANGES
    // FIXME: What are we going to do for this case?
#else
    // First we need to find out the servicetype - again - this code is too duplicated !
    HTMLEmbedElementImpl *embed = 0;
    QString serviceType;
    if( element()->id()==ID_OBJECT ) {

        // check for embed child object
        HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element());
        serviceType = o->serviceType;
        NodeImpl *child = o->firstChild();
        while ( child ) {
            if ( child->id() == ID_EMBED )
                embed = static_cast<HTMLEmbedElementImpl *>( child );

            child = child->nextSibling();
        }

    } else if( element()->id()==ID_EMBED ) {
        embed = static_cast<HTMLEmbedElementImpl *>(element());
    }
    if ( embed )
    serviceType = embed->serviceType;

    KHTMLPart *part = static_cast<KHTMLView *>(m_view)->part();
    KParts::BrowserExtension *ext = part->browserExtension();
    if( embed && !embed->pluginPage.isEmpty() && ext ) {
        // Prepare the mimetype to show in the question (comment if available, name as fallback)
        QString mimeName = serviceType;
        KMimeType::Ptr mime = KMimeType::mimeType(serviceType);
        if ( mime->name() != KMimeType::defaultMimeType() )
            mimeName = mime->comment();
        // Prepare the URL to show in the question (host only if http, to make it short)
        KURL pluginPageURL( embed->pluginPage );
        QString shortURL = pluginPageURL.protocol() == "http" ? pluginPageURL.host() : pluginPageURL.prettyURL();
        int res = KMessageBox::questionYesNo( m_view,
            i18n("No plugin found for '%1'.\nDo you want to download one from %2?").arg(mimeName).arg(shortURL),
        i18n("Missing plugin"), QString::null, QString::null, QString("plugin-")+serviceType);
    if ( res == KMessageBox::Yes )
    {
          // Display vendor download page
          ext->createNewWindow( pluginPageURL );
    }
    }
#endif // APPLE_CHANGES
}

void RenderPartObject::layout( )
{
    KHTMLAssert( needsLayout() );
    KHTMLAssert( minMaxKnown() );

#if !APPLE_CHANGES
    int m_oldwidth = m_width;
    int m_oldheight = m_height;
#endif

    calcWidth();
    calcHeight();

    RenderPart::layout();

    setNeedsLayout(false);
}

void RenderPartObject::slotViewCleared()
{
  if(element() && m_widget && m_widget->inherits("QScrollView") ) {
#ifdef DEBUG_LAYOUT
      kdDebug(6031) << "iframe is a scrollview!" << endl;
#endif
      QScrollView *view = static_cast<QScrollView *>(m_widget);
      int frameStyle = QFrame::NoFrame;
      QScrollView::ScrollBarMode scroll = QScrollView::Auto;
      int marginw = -1;
      int marginh = -1;
      if ( element()->id() == ID_IFRAME) {
      HTMLIFrameElementImpl *frame = static_cast<HTMLIFrameElementImpl *>(element());
      if(frame->frameBorder)
          frameStyle = QFrame::Box;
          scroll = frame->scrolling;
      marginw = frame->marginWidth;
      marginh = frame->marginHeight;
      }
      view->setFrameStyle(frameStyle);

#if !APPLE_CHANGES
      view->setVScrollBarMode(scroll);
      view->setHScrollBarMode(scroll);
#endif

      if(view->inherits("KHTMLView")) {
#ifdef DEBUG_LAYOUT
          kdDebug(6031) << "frame is a KHTMLview!" << endl;
#endif
          KHTMLView *htmlView = static_cast<KHTMLView *>(view);
          htmlView->setIgnoreWheelEvents( element()->id() == ID_IFRAME );
          if(marginw != -1) htmlView->setMarginWidth(marginw);
          if(marginh != -1) htmlView->setMarginHeight(marginh);
        }
  }
}

#if APPLE_CHANGES
// FIXME: This should not be necessary.  Remove this once WebKit knows to properly schedule
// layouts using WebCore when objects resize.
void RenderPart::updateWidgetPositions()
{
    if (!m_widget)
        return;

    int x, y, width, height;
    absolutePosition(x,y);
    x += borderLeft() + paddingLeft();
    y += borderTop() + paddingTop();
    width = m_width - borderLeft() - borderRight() - paddingLeft() - paddingRight();
    height = m_height - borderTop() - borderBottom() - paddingTop() - paddingBottom();
    QRect newBounds(x,y,width,height);
    if (newBounds != m_widget->frameGeometry()) {
        // The widget changed positions.  Update the frame geometry.
        RenderArena *arena = ref();
        element()->ref();
        m_widget->setFrameGeometry(newBounds);
        element()->deref();
        deref(arena);

        QScrollView *view = static_cast<QScrollView *>(m_widget);
#if !NOKIA_CHANGES
        if (view && view->inherits("KHTMLView"))
            static_cast<KHTMLView*>(view)->layout();
#endif
    }
}
#endif

#include "render_frames.moc"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -