📄 khtmlview.cpp
字号:
khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer()); if ( !root ) return; int docw = root->docWidth(); int doch = root->docHeight(); resizeContents(docw, doch); }}void KHTMLView::applyBodyScrollQuirk(khtml::RenderObject* o, ScrollBarMode& hMode, ScrollBarMode& vMode){ // Handle the overflow:hidden/scroll quirk for the body elements. WinIE treats // overflow:hidden and overflow:scroll on <body> as applying to the document's // scrollbars. The CSS2.1 draft has even added a sentence, "HTML UAs may apply overflow // specified on the body or HTML elements to the viewport." Since WinIE and Mozilla both // do it, we will do it too for <body> elements. switch(o->style()->overflow()) { case OHIDDEN: hMode = vMode = AlwaysOff; break; case OSCROLL: hMode = vMode = AlwaysOn; break; case OAUTO: hMode = vMode = Auto; break; default: // Don't set it at all. ; }}bool KHTMLView::inLayout() const{ return d->layoutSuppressed;}int KHTMLView::layoutCount() const{ return d->layoutCount;}bool KHTMLView::needsFullRepaint() const{ return d->doFullRepaint;}void KHTMLView::addRepaintInfo(RenderObject* o, const QRect& r){ if (!d->repaintRects) { d->repaintRects = new QPtrList<RenderObject::RepaintInfo>; d->repaintRects->setAutoDelete(true); } d->repaintRects->append(new RenderObject::RepaintInfo(o, r));}void KHTMLView::layout(){ if (d->layoutSuppressed) return; d->layoutSchedulingEnabled=false; killTimer(d->layoutTimerId); d->layoutTimerId = 0; d->allDataReceivedWhenTimerSet = false; if (!m_part) { // FIXME: Do we need to set _width here? // FIXME: Should we set _height here too? _width = visibleWidth(); return; } DOM::DocumentImpl* document = m_part->xmlDocImpl(); if (!document) { // FIXME: Should we set _height here too? _width = visibleWidth(); return; } khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas*>(document->renderer()); if (!root) { // FIXME: Do we need to set _width or _height here? return; } ScrollBarMode hMode = d->hmode; ScrollBarMode vMode = d->vmode; if (document->isHTMLDocument()) { NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body(); if (body && body->renderer()) { if (body->id() == ID_FRAMESET) { body->renderer()->setNeedsLayout(true); vMode = AlwaysOff; hMode = AlwaysOff; } else if (body->id() == ID_BODY) applyBodyScrollQuirk(body->renderer(), hMode, vMode); // Only applies to HTML UAs, not to XML/XHTML UAs } }#ifdef INSTRUMENT_LAYOUT_SCHEDULING if (d->firstLayout && !document->ownerElement()) printf("Elapsed time before first layout: %d\n", document->elapsedTime());#endif d->doFullRepaint = d->firstLayout || root->printingMode(); if (d->repaintRects) d->repaintRects->clear();#if APPLE_CHANGES // Now set our scrollbar state for the layout. ScrollBarMode currentHMode = hScrollBarMode(); ScrollBarMode currentVMode = vScrollBarMode(); if (d->firstLayout || (hMode != currentHMode || vMode != currentVMode)) { suppressScrollBars(true); if (d->firstLayout) { d->firstLayout = false; // Set the initial vMode to AlwaysOn if we're auto. if (vMode == Auto) QScrollView::setVScrollBarMode(AlwaysOn); // This causes a vertical scrollbar to appear. // Set the initial hMode to AlwaysOff if we're auto. if (hMode == Auto) QScrollView::setHScrollBarMode(AlwaysOff); // This causes a horizontal scrollbar to disappear. } if (hMode == vMode) QScrollView::setScrollBarsMode(hMode); else { QScrollView::setHScrollBarMode(hMode); QScrollView::setVScrollBarMode(vMode); } suppressScrollBars(false, true); }#else QScrollView::setHScrollBarMode(hMode); QScrollView::setVScrollBarMode(vMode);#endif int oldHeight = _height; int oldWidth = _width; _height = visibleHeight(); _width = visibleWidth(); if (oldHeight != _height || oldWidth != _width) d->doFullRepaint = true; RenderLayer* layer = root->layer(); if (!d->doFullRepaint) { layer->computeRepaintRects(); root->repaintObjectsBeforeLayout(); } root->layout(); m_part->invalidateSelection(); //kdDebug( 6000 ) << "TIME: layout() dt=" << qt.elapsed() << endl; d->layoutSchedulingEnabled=true; d->layoutSuppressed = false; if (!root->printingMode()) resizeContents(layer->width(), layer->height()); // Now update the positions of all layers. layer->updateLayerPositions(d->doFullRepaint);#if APPLE_CHANGES // We update our widget positions right after doing a layout. root->updateWidgetPositions();#endif if (d->repaintRects && !d->repaintRects->isEmpty()) { // FIXME: Could optimize this and have objects removed from this list // if they ever do full repaints. RenderObject::RepaintInfo* r; QPtrListIterator<RenderObject::RepaintInfo> it(*d->repaintRects); for ( ; (r = it.current()); ++it) r->m_object->repaintRectangle(r->m_repaintRect); d->repaintRects->clear(); } d->layoutCount++;#if APPLE_CHANGES if (KWQAccObjectCache::accessibilityEnabled()) root->document()->getOrCreateAccObjectCache()->postNotification(root, "AXLayoutComplete");#endif if (root->needsLayout()) { //qDebug("needs layout, delaying repaint"); scheduleRelayout(); return; } setStaticBackground(d->useSlowRepaints);}//// Event Handling///////////////////void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse ){ if(!m_part->xmlDocImpl()) return; int xm, ym; viewportToContents(_mouse->x(), _mouse->y(), xm, ym); //kdDebug( 6000 ) << "\nmousePressEvent: x=" << xm << ", y=" << ym << endl; d->isDoubleClick = false; d->mousePressed = true; DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MousePress ); m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );#if !APPLE_CHANGES if (d->clickCount > 0 && QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance()) d->clickCount++; else { d->clickCount = 1; d->clickX = xm; d->clickY = ym; }#else if (KWQ(m_part)->passSubframeEventToSubframe(mev)) return; d->clickX = xm; d->clickY = ym; d->clickCount = _mouse->clickCount();#endif bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),true, d->clickCount,_mouse,true,DOM::NodeImpl::MousePress); if (!swallowEvent) { khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode ); QApplication::sendEvent( m_part, &event );#if APPLE_CHANGES // Many AK widgets run their own event loops and consume events while the mouse is down. // When they finish, currentEvent is the mouseUp that they exited on. We need to update // the khtml state with this mouseUp, which khtml never saw. // If this event isn't a mouseUp, we assume that the mouseUp will be coming later. There // is a hole here if the widget consumes the mouseUp and subsequent events. if (KWQ(m_part)->lastEventIsMouseUp()) { d->mousePressed = false; }#endif emit m_part->nodeActivated(mev.innerNode); }}void KHTMLView::viewportMouseDoubleClickEvent( QMouseEvent *_mouse ){ if(!m_part->xmlDocImpl()) return; int xm, ym; viewportToContents(_mouse->x(), _mouse->y(), xm, ym); //kdDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym << endl; d->isDoubleClick = true;#if APPLE_CHANGES // We get this instead of a second mouse-up d->mousePressed = false;#endif DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseDblClick ); m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );#if APPLE_CHANGES if (KWQ(m_part)->passSubframeEventToSubframe(mev)) return; d->clickCount = _mouse->clickCount(); bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,mev.innerNode.handle(),true, d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease); dispatchMouseEvent(EventImpl::CLICK_EVENT,mev.innerNode.handle(),true, d->clickCount,_mouse,true,DOM::NodeImpl::MouseRelease); // Qt delivers a release event AND a double click event. if (!swallowEvent) { khtml::MouseReleaseEvent event1( _mouse, xm, ym, mev.url, mev.target, mev.innerNode ); QApplication::sendEvent( m_part, &event1 ); khtml::MouseDoubleClickEvent event2( _mouse, xm, ym, mev.url, mev.target, mev.innerNode ); QApplication::sendEvent( m_part, &event2 ); }#else // We do the same thing as viewportMousePressEvent() here, since the DOM does not treat // single and double-click events as separate (only the detail, i.e. number of clicks differs) // In other words an even detail value for a mouse click event means a double click, and an // odd detail value means a single click bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),true, d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick); if (!swallowEvent) { khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode ); QApplication::sendEvent( m_part, &event ); // ### //if ( url.length() ) //emit doubleClick( url.string(), _mouse->button() ); }#endif }static bool isSubmitImage(DOM::NodeImpl *node){ return node && node->isHTMLElement() && node->id() == ID_INPUT && static_cast<HTMLInputElementImpl*>(node)->inputType() == HTMLInputElementImpl::IMAGE;}void KHTMLView::viewportMouseMoveEvent( QMouseEvent * _mouse ){ if(!m_part->xmlDocImpl()) return; int xm, ym; viewportToContents(_mouse->x(), _mouse->y(), xm, ym); // Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent. // This means that :hover and :active freeze in the state they were in when the mouse // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down. DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseMove ); m_part->xmlDocImpl()->prepareMouseEvent( d->mousePressed, xm, ym, &mev );#if APPLE_CHANGES if (KWQ(m_part)->passSubframeEventToSubframe(mev)) return;#endif bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,mev.innerNode.handle(),false, 0,_mouse,true,DOM::NodeImpl::MouseMove);#if !APPLE_CHANGES if (d->clickCount > 0 && QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() > QApplication::startDragDistance()) { d->clickCount = 0; // moving the mouse outside the threshold invalidates the click }#endif // execute the scheduled script. This is to make sure the mouseover events come after the mouseout events m_part->executeScheduledScript(); khtml::RenderStyle* style = (mev.innerNode.handle() && mev.innerNode.handle()->renderer() && mev.innerNode.handle()->renderer()->style()) ? mev.innerNode.handle()->renderer()->style() : 0; QCursor c; if (style && style->cursor() == CURSOR_AUTO && style->cursorImage() && !(style->cursorImage()->pixmap().isNull())) { /* First of all it works: Check out http://www.iam.unibe.ch/~schlpbch/cursor.html * * But, I don't know what exactly we have to do here: rescale to 32*32, change to monochrome.. */ //kdDebug( 6000 ) << "using custom cursor" << endl; const QPixmap p = style->cursorImage()->pixmap(); // ### fix c = QCursor(p); } switch ( style ? style->cursor() : CURSOR_AUTO) { case CURSOR_AUTO: if ( d->mousePressed && m_part->hasSelection() ) // during selection, use an IBeam no matter what we're over c = KCursor::ibeamCursor(); else if ( (!mev.url.isNull() || isSubmitImage(mev.innerNode.handle())) && m_part->settings()->changeCursor() ) c = m_part->urlCursor(); else if ( !mev.innerNode.isNull() && (mev.innerNode.nodeType() == Node::TEXT_NODE || mev.innerNode.nodeType() == Node::CDATA_SECTION_NODE || (mev.innerNode.isContentEditable()))) c = KCursor::ibeamCursor(); break; case CURSOR_CROSS: c = KCursor::crossCursor(); break; case CURSOR_POINTER: c = m_part->urlCursor(); break; case CURSOR_MOVE: c = KCursor::sizeAllCursor(); break; case CURSOR_E_RESIZE:#if APPLE_CHANGES c = KCursor::eastResizeCursor(); break;#endif case CURSOR_W_RESIZE:#if APPLE_CHANGES c = KCursor::westResizeCursor();#else c = KCursor::sizeHorCursor();#endif break; case CURSOR_N_RESIZE:#if APPLE_CHANGES c = KCursor::northResizeCursor(); break;#endif case CURSOR_S_RESIZE:#if APPLE_CHANGES c = KCursor::southResizeCursor();#else c = KCursor::sizeVerCursor();#endif break; case CURSOR_NE_RESIZE:#if APPLE_CHANGES c = KCursor::northEastResizeCursor(); break;#endif case CURSOR_SW_RESIZE:#if APPLE_CHANGES c = KCursor::southWestResizeCursor();#else c = KCursor::sizeBDiagCursor();#endif break; case CURSOR_NW_RESIZE:#if APPLE_CHANGES c = KCursor::northWestResizeCursor(); break;#endif case CURSOR_SE_RESIZE:#if APPLE_CHANGES c = KCursor::southEastResizeCursor();#else c = KCursor::sizeFDiagCursor();#endif break; case CURSOR_TEXT: c = KCursor::ibeamCursor(); break; case CURSOR_WAIT: c = KCursor::waitCursor(); break; case CURSOR_HELP: c = KCursor::whatsThisCursor(); break; case CURSOR_DEFAULT: break; } QWidget *vp = viewport(); if ( vp->cursor().handle() != c.handle() ) { if( c.handle() == KCursor::arrowCursor().handle()) vp->unsetCursor(); else vp->setCursor( c ); } d->prevMouseX = xm; d->prevMouseY = ym; if (!swallowEvent) { khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode ); QApplication::sendEvent( m_part, &event ); }}void KHTMLView::resetCursor(){ viewport()->unsetCursor();}void KHTMLView::invalidateClick(){ d->clickCount = 0;}void KHTMLView::viewportMouseReleaseEvent( QMouseEvent * _mouse ){ if ( !m_part->xmlDocImpl() ) return; int xm, ym; viewportToContents(_mouse->x(), _mouse->y(), xm, ym); d->mousePressed = false; //kdDebug( 6000 ) << "\nmouseReleaseEvent: x=" << xm << ", y=" << ym << endl; DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseRelease ); m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );#if APPLE_CHANGES if (KWQ(m_part)->passSubframeEventToSubframe(mev)) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -