Summary: | [test case] a fixed (with css) text/html <object> "jumps" when scrolling | ||
---|---|---|---|
Product: | [Applications] konqueror | Reporter: | Panther Wyvern <panther> |
Component: | khtml renderer | Assignee: | Konqueror Developers <konq-bugs> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | zyzstar |
Priority: | NOR | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
Platform: | openSUSE | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | |||
Attachments: |
example of jumping elements
small html file loaded into main document via <object> small html file loaded into main document via <object> example of jumping elements |
Description
Panther Wyvern
2003-11-21 10:09:21 UTC
It would be good to have an example of the bug to reproduce or to see it it is fixed in the new versions. I just downloaded and installed the SuSE builds of KDE 3.1.4. Konqueror acts the same. I have slapped together a quick example and put it up here: http://www.mylinuxisp.com/~panther/konqueror.html All of the css attributes are in the main document. I have four fixed elements - two are contained in the main document (one with image, one without) and two are inline object frames from smaller html files. Scroll through the page and see how the object frames jump because of their fixed position while the other two do not. A funny thing I just noticed is that if you scroll the page with the mouse wheel, arrow keys, scrollbar buttons or the scrollbar itself, the object frames jump while the paragraphs within the main document stay still. However, if you scroll using PageUp/PageDown, the object frames remain still while the paragraphs within the main document jump. Try it. Can you perhaps reduce it a bit more and attach it here? KDE 3.2 will behave the same :) Created attachment 3378 [details]
example of jumping elements
This is the first time I'm attaching here... I hope I'm not screwing this up.
:)
Created attachment 3379 [details]
small html file loaded into main document via <object>
Created attachment 3380 [details]
small html file loaded into main document via <object>
Created attachment 3381 [details]
example of jumping elements
Okay, I messed up before but I *think* I have a better grasp on it now. :)
Well, I can confirm this with KDE CVS 3.1.93. When scrolling, the <object>s rendering is very unstable; they certainly jump a lot, and sometimes, even vanish. With Mozilla Firebird, the objects remain in their fixed position, and they are rendered in subwindows that also get scrollbars. Just in case this could be a duplicate, this bug is also related to <object> rendering : http://bugs.kde.org/show_bug.cgi?id=61286. i am experiencing the same problem. position fixed and either a <object> or an <iframe> result in the described manner. i am using kde 3.3 so this is still valid :( Same here with KDE 3.3. I put up an example page at http://members.lycos.co.uk/alexv6/test.html . the iframe element there jumps a lot. That would be torelable if it didn't vanish sometimes. updating, still valid in kde 3.4.3 *** Bug 125910 has been marked as a duplicate of this bug. *** SVN commit 630479 by ggarand: A simple "page scaling" zoom à la Opera. For now, it replaces the font scaling action, as the method names used for it in KHTML part are better suited to a real zoom (e.g. setZoomFactor). Need to reintroduce pure font-scaling under another name.. Also introduce an alternate, non-blitting painting mode for being able to do fixed positioning again. QScrollArea's quite a bit on the terse side, so there was no such thing ;( Should fix widget jittering issues as a bonus. BUG: 42029, 68721 M +2 -2 css/cssstyleselector.cpp M +9 -4 khtml_part.cpp M +111 -18 khtmlview.cpp M +20 -1 khtmlview.h M +15 -8 rendering/render_canvas.cpp M +1 -1 rendering/render_replaced.cpp M +2 -0 xml/dom_nodeimpl.cpp --- trunk/KDE/kdelibs/khtml/css/cssstyleselector.cpp #630478:630479 @@ -749,7 +749,7 @@ // FIXME: We only need to invalidate the fixed regions when scrolling. It's total overkill to // prevent the entire view from blitting on a scroll. if (style->hasFixedBackgroundImage() && view) - view->useSlowRepaints(); + view->setHasStaticBackground(); } unsigned int CSSStyleSelector::addInlineDeclarations(DOM::ElementImpl* e, @@ -2414,7 +2414,7 @@ p = ABSOLUTE; break; case CSS_VAL_FIXED: { - view->useSlowRepaints(); + view->setHasStaticBackground(); p = FIXED; break; } --- trunk/KDE/kdelibs/khtml/khtml_part.cpp #630478:630479 @@ -5754,11 +5754,16 @@ if (d->m_zoomFactor == percent) return; d->m_zoomFactor = percent; - if(d->m_doc) { + if(d->m_view) { QApplication::setOverrideCursor( Qt::WaitCursor ); - if (d->m_doc->styleSelector()) - d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor); - d->m_doc->recalcStyle( NodeImpl::Force ); + +// ### make the increasing/decreasing of font size a separate setting +// +// if (d->m_doc->styleSelector()) +// d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor); +// d->m_doc->recalcStyle( NodeImpl::Force ); + + d->m_view->setZoomLevel( d->m_zoomFactor ); QApplication::restoreOverrideCursor(); } --- trunk/KDE/kdelibs/khtml/khtmlview.cpp #630478:630479 @@ -186,10 +186,11 @@ oldUnderMouse->deref(); oldUnderMouse = 0; linkPressed = false; - useSlowRepaints = false; + staticWidget = false; tabMovePending = false; lastTabbingDirection = true; pseudoFocusNode = PFNone; + zoomLevel = 100; #ifndef KHTML_NO_SCROLLBARS //We don't turn off the toolbars here //since if the user turns them @@ -287,6 +288,8 @@ scrollSuspended = false; } + bool haveZoom() const { return zoomLevel != 100; } + #ifndef KHTML_NO_CARET /** this function returns an instance of the caret view context. If none * exists, it will be instantiated. @@ -324,9 +327,10 @@ Qt::ScrollBarPolicy hpolicy; bool prevScrollbarVisible:1; bool linkPressed:1; - bool useSlowRepaints:1; + bool staticWidget:1; bool ignoreWheelEvents:1; + int zoomLevel; int borderX, borderY; KSimpleConfig *formCompletions; @@ -510,9 +514,13 @@ QSize s = viewport()->size(); resizeContents(s.width(), s.height()); - // ### we'll enable redirection of khtmlview here - // when event and painting issues have been thoroughly worked out - // m_kwp->setIsRedirected(true); + // ### we'll enable redirection of khtmlview + // when event issues have been thoroughly worked out + + bool redirect = false; // m_part->parentPart() && !isFrame() ... + + m_kwp->setIsRedirected( redirect ); + d->staticWidget = redirect; } void KHTMLView::clear() @@ -640,6 +648,7 @@ void KHTMLView::updateContents(int x, int y, int w, int h) { + applyTransforms(x, y, w, h); widget()->update(x, y, w, h); } @@ -650,6 +659,7 @@ void KHTMLView::repaintContents(int x, int y, int w, int h) { + applyTransforms(x, y, w, h); widget()->repaint(x, y, w, h); } @@ -658,6 +668,42 @@ repaintContents( r.x(), r.y(), r.width(), r.height() ); } +void KHTMLView::applyTransforms( int& x, int& y, int& w, int& h) const +{ + if (d->staticWidget) { + x -= contentsX(); + y -= contentsY(); + } + if (d->haveZoom()) { + const int z = d->zoomLevel; + x = x*z/100; + y = y*z/100; + w = w*z/100; + h = h*z/100; + } +} + +void KHTMLView::revertTransforms( int& x, int& y, int& w, int& h) const +{ + if (d->staticWidget) { + x += contentsX(); + y += contentsY(); + } + if (d->haveZoom()) { + const int z = d->zoomLevel; + x = x*100/z; + y = y*100/z; + w = w*100/z; + h = h*100/z; + } +} + +void KHTMLView::revertTransforms( int& x, int& y ) const +{ + int dummy = 0; + revertTransforms(x, y, dummy, dummy); +} + void KHTMLView::resizeEvent (QResizeEvent* e) { int dw = e->oldSize().width() - e->size().width(); @@ -692,16 +738,30 @@ QRect r = e->rect(); QRect v(contentsX(), contentsY(), visibleWidth(), visibleHeight()); + if (d->staticWidget) { + QPoint off(contentsX(),contentsY()); + p.translate(-off); + r.translate(off); + } r = r.intersect(v); if (!r.isValid() || r.isEmpty()) return; - p.setClipRect(v); + + if (d->haveZoom()) { + p.scale( d->zoomLevel/100., d->zoomLevel/100.); + r.setX(r.x()*100/d->zoomLevel); + r.setY(r.y()*100/d->zoomLevel); + r.setWidth(r.width()*100/d->zoomLevel); + r.setHeight(r.height()*100/d->zoomLevel); + } + p.setClipRect(r); + int ex = r.x(); int ey = r.y(); int ew = r.width(); int eh = r.height(); - + if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) { p.fillRect(ex, ey, ew, eh, palette().brush(QPalette::Active, QPalette::Base)); return; @@ -882,6 +942,23 @@ QScrollArea::closeEvent( ev ); } +void KHTMLView::setZoomLevel(int percent) +{ + percent = percent < 20 ? 20 : (percent > 800 ? 800 : percent); + int oldpercent = d->zoomLevel; + d->zoomLevel = percent; + if (percent != oldpercent) { + if (d->layoutSchedulingEnabled) + layout(); + widget()->update(); + } +} + +int KHTMLView::zoomLevel() const +{ + return d->zoomLevel; +} + // // Event Handling // @@ -898,6 +975,7 @@ int xm = _mouse->x(); int ym = _mouse->y(); + revertTransforms(xm, ym); // kDebug( 6000 ) << "mousePressEvent: viewport=("<<_mouse->x()-contentsX()<<"/"<<_mouse->y()-contentsY()<<"), contents=(" << xm << "/" << ym << ")\n"; @@ -1018,6 +1096,7 @@ int xm = _mouse->x(); int ym = _mouse->y(); + revertTransforms(xm, ym); // kDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym << endl; @@ -1087,6 +1166,7 @@ int xm = _mouse->x(); int ym = _mouse->y(); + revertTransforms(xm, ym); DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MouseMove ); // Do not modify :hover/:active state while mouse is pressed. @@ -1240,6 +1320,7 @@ int xm = _mouse->x(); int ym = _mouse->y(); + revertTransforms(xm, ym); DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MouseRelease ); @@ -3001,10 +3082,11 @@ } -void KHTMLView::useSlowRepaints() +void KHTMLView::setHasStaticBackground() { - d->useSlowRepaints = true; -// setStaticBackground(true); ### ?? FIXME + if (!d->staticWidget) + widget()->move(0,0); + d->staticWidget = true; } @@ -3136,6 +3218,7 @@ int exceptioncode = 0; int pageX = _mouse->x(); int pageY = _mouse->y(); + revertTransforms(pageX, pageY); int clientX = pageX - contentsX(); int clientY = pageY - contentsY(); int screenX = _mouse->globalX(); @@ -3164,7 +3247,7 @@ // mouseout/mouseover if (setUnder && d->oldUnderMouse != targetNode) { - if (d->oldUnderMouse && d->oldUnderMouse->getDocument() != targetNode->getDocument()) { + if (d->oldUnderMouse && d->oldUnderMouse->getDocument() != m_part->xmlDocImpl()) { d->oldUnderMouse->deref(); d->oldUnderMouse = 0; } @@ -3436,16 +3519,29 @@ horizontalScrollBar()->maximum()-horizontalScrollBar()->value() : horizontalScrollBar()->value(); d->contentsY = verticalScrollBar()->value(); - if (d->useSlowRepaints) { - widget()->blockSignals( true ); - widget()->move( widget()->pos().x() + dx, widget()->pos().y() +dy ); - widget()->blockSignals( false ); + if ( d->staticWidget ) { widget()->repaint(); return; } QScrollArea::scrollContentsBy(dx, dy); } +void KHTMLView::addChild(QWidget * child, int x, int y) +{ + if (!child) + return; + + if (child->parent() != widget()) + child->setParent( widget() ); + + // ### handle pseudo-zooming of non-redirected widgets (e.g. just resize'em) + + if (!d->staticWidget) + child->move(x, y); + else + child->move(x-contentsX(), y-contentsY()); +} + void KHTMLView::timerEvent ( QTimerEvent *e ) { // kDebug() << "timer event " << e->timerId() << endl; @@ -3518,9 +3614,6 @@ } } -// setStaticBackground(d->useSlowRepaints); ?? ### FIXME - -// kDebug() << "scheduled repaint "<< d->repaintTimerId << endl; if (d->repaintTimerId) killTimer(d->repaintTimerId); d->repaintTimerId = 0; --- trunk/KDE/kdelibs/khtml/khtmlview.h #630478:630479 @@ -98,6 +98,7 @@ friend class DOM::HTMLFormElementImpl; friend class DOM::HTMLAnchorElementImpl; friend class DOM::HTMLInputElementImpl; + friend class DOM::NodeImpl; friend class DOM::DocumentImpl; friend class KHTMLPart; friend class khtml::RenderCanvas; @@ -257,6 +258,8 @@ */ void updateContents( const QRect& r ); void updateContents(int x, int y, int w, int h); + + void addChild(QWidget *child, int dx, int dy); /** * Requests an immediate repaint of the content area @@ -264,6 +267,18 @@ */ void repaintContents( const QRect& r ); void repaintContents(int x, int y, int w, int h); + + /** + * Apply a zoom level to the content area + * @param percent a zoom level expressed as a percentage + */ + void setZoomLevel( int percent ); + + /** + * Retrieve the current zoom level + * + */ + int zoomLevel() const; public Q_SLOTS: /** @@ -393,7 +408,10 @@ QMap< DOM::ElementImpl*, QChar > buildFallbackAccessKeys() const; void displayAccessKeys( KHTMLView* caller, KHTMLView* origview, QVector< QChar >& taken, bool use_fallbacks ); - void useSlowRepaints(); + void setHasStaticBackground(); + void applyTransforms( int& x, int& y, int& w, int& h) const; + void revertTransforms( int& x, int& y, int& w, int& h) const; + void revertTransforms( int& x, int& y ) const; void setIgnoreWheelEvents(bool e); @@ -699,6 +717,7 @@ void setWidgetVisible(::khtml::RenderWidget*, bool visible); + int _width; int _height; --- trunk/KDE/kdelibs/khtml/rendering/render_canvas.cpp #630478:630479 @@ -220,35 +220,42 @@ // update our cached document size int hDocH = m_cachedDocHeight = docHeight(); int hDocW = m_cachedDocWidth = docWidth(); + + int zLevel = m_view? m_view->zoomLevel() : 100; + hDocW = hDocW*zLevel/100; + hDocH = hDocH*zLevel/100; if (!m_pagedMode && m_view) { bool vss = !m_view->verticalScrollBar()->isHidden(); bool hss = !m_view->horizontalScrollBar()->isHidden(); QSize s = m_view->maximumViewportSize(); - if ( m_cachedDocWidth > s.width() ) + + int zoomedDocWidth = m_cachedDocWidth*zLevel/100; + int zoomedDocHeight = m_cachedDocHeight*zLevel/100; + if ( zoomedDocWidth > s.width() ) s.setWidth( s.width()-m_view->verticalScrollBar()->sizeHint().width() ); - if ( m_cachedDocHeight > s.height() ) + if ( zoomedDocHeight > s.height() ) s.setHeight( s.height()-m_view->horizontalScrollBar()->sizeHint().height() ); // if we are about to show a scrollbar, and the document is sized to the viewport w or h, // then reserve the scrollbar space so that it doesn't trigger the _other_ scrollbar if (!vss && m_width - m_view->verticalScrollBar()->sizeHint().width() == s.width() && - m_cachedDocWidth <= m_width) - hDocW = qMin( m_cachedDocWidth, s.width() ); + zoomedDocWidth <= m_width) + hDocW = qMin( zoomedDocWidth, s.width() ); if (!hss && m_height - m_view->horizontalScrollBar()->sizeHint().height() == s.height() && - m_cachedDocHeight <= m_height) - hDocH = qMin( m_cachedDocHeight, s.height() ); + zoomedDocHeight <= m_height) + hDocH = qMin( zoomedDocHeight, s.height() ); // likewise, if a scrollbar is shown, and we have a cunning plan to turn it off, // think again if we are falling downright in the hysteresis zone - if (vss && s.width() > m_cachedDocWidth && m_cachedDocWidth > m_view->visibleWidth()) + if (vss && s.width() > zoomedDocWidth && zoomedDocWidth > m_view->visibleWidth()) hDocW = s.width()+1; - if (hss && s.height() > m_cachedDocHeight && m_cachedDocHeight > m_view->visibleHeight()) + if (hss && s.height() > zoomedDocHeight && zoomedDocHeight > m_view->visibleHeight()) hDocH = s.height()+1; m_view->resizeContents(hDocW, hDocH); --- trunk/KDE/kdelibs/khtml/rendering/render_replaced.cpp #630478:630479 @@ -524,7 +524,7 @@ } m_view->setWidgetVisible(this, true); if (!khtmlw) - m_widget->move( xPos, yPos ); + m_view->addChild( m_widget, xPos, yPos ); else m_widget->move( xPos, -500000 +yPos); m_widget->show(); --- trunk/KDE/kdelibs/khtml/xml/dom_nodeimpl.cpp #630478:630479 @@ -503,6 +503,8 @@ int exceptioncode = 0; int pageX = _mouse->x(); int pageY = _mouse->y(); + if ( getDocument()->view() ) + getDocument()->view()->revertTransforms( pageX, pageY ); int clientX = pageX; int clientY = pageY; if ( getDocument()->view() ) |