smooth scrolling comment

Koos Vriezen koos.vriezen at xs4all.nl
Wed Jul 31 16:09:29 BST 2002


On Tue, 30 Jul 2002, Koos Vriezen wrote:

> On Tue, 30 Jul 2002, Hetz Ben Hamo wrote:
>
> > 1. In order to stop the scrolling - only the up key stops. Why not any key?
> > I'm pretty sure end user would be pissed to find that they can't stop smooth
> > scrolling unless they find that arrow up stops it.
>
> That wouldn't be to difficult to implement. Personaly I like the
> combination of auto scrolling and PgUp/PgDown to quickly scan news sites.
> But for other, non-scrolling keys, yes why not.
>
> > 2. Is there going to be also a smooth scrolling upwards and sideways please?
> > it will help a lot with large tables..
>
> Scrolling up, wouldn't be hard to implement. Scrolling right/left needs
> imo some changes in paintBuffer, an extra vertical or rotation by
> drawPixmap. However the usefulness, compared to scrolling down, is a lot
> less.

Well for completing this auto scroller thing, here a patch that does the
above.
I've added a 10 by visualHeight vertical paintBuffer for smooth horizontal
scrolling. Besides that, the patch is quite boring.

Regards,

Koos Vriezen
-------------- next part --------------
Index: khtmlview.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/khtmlview.cpp,v
retrieving revision 1.478
diff -u -3 -p -r1.478 khtmlview.cpp
--- khtmlview.cpp	2002/07/30 15:36:48	1.478
+++ khtmlview.cpp	2002/07/31 15:10:24
@@ -60,6 +60,10 @@
 
 #define PAINT_BUFFER_HEIGHT 128
 
+#define NEWSCROLLTIMER(x)                                \
+{   kdDebug() << "timer event killing timer" << endl;    \
+    killTimer(d->scrollTimerId); d->scrollTimerId = (x); }
+
 using namespace DOM;
 using namespace khtml;
 class KHTMLToolTip;
@@ -94,6 +98,7 @@ public:
         reset();
         tp=0;
         paintBuffer=0;
+        vertPaintBuffer=0;
         formCompletions=0;
         prevScrollbarVisible = true;
 	timerId = 0;
@@ -107,6 +112,7 @@ public:
         delete formCompletions;
         delete tp; tp = 0;
         delete paintBuffer; paintBuffer =0;
+        delete vertPaintBuffer;
         if (underMouse)
 	    underMouse->deref();
 	delete tooltip;
@@ -149,6 +155,7 @@ public:
 
     QPainter *tp;
     QPixmap  *paintBuffer;
+    QPixmap  *vertPaintBuffer;
     NodeImpl *underMouse;
 
     // the node that was selected when enter was pressed
@@ -179,6 +186,7 @@ public:
     int scrollTimerId;
     int scrollTiming;
     int scrollBy;
+    enum { ScrollLeft, ScrollRight, ScrollUp, ScrollDown } scrollDirection;
     bool complete;
     bool firstRelayout;
     bool layoutSchedulingEnabled;
@@ -249,6 +257,8 @@ KHTMLView::~KHTMLView()
 void KHTMLView::init()
 {
     if(!d->paintBuffer) d->paintBuffer = new QPixmap(PAINT_BUFFER_HEIGHT, PAINT_BUFFER_HEIGHT);
+    if(!d->vertPaintBuffer) 
+        d->vertPaintBuffer = new QPixmap(10, PAINT_BUFFER_HEIGHT);
     if(!d->tp) d->tp = new QPainter();
 
     setFocusPolicy(QWidget::StrongFocus);
@@ -327,28 +337,40 @@ void KHTMLView::drawContents( QPainter *
     if(!m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
         p->fillRect(ex, ey, ew, eh, palette().normal().brush(QColorGroup::Base));
         return;
+    }
+    if (eh > PAINT_BUFFER_HEIGHT && ew <= 10) {
+        if ( d->vertPaintBuffer->height() < visibleHeight() )
+            d->vertPaintBuffer->resize(10, visibleHeight());
+        d->tp->begin(d->vertPaintBuffer);
+        d->tp->translate(-ex, -ey);
+        d->tp->fillRect(ex, ey, ew, eh, palette().normal().brush(QColorGroup::Base));
+        m_part->xmlDocImpl()->renderer()->print(d->tp, ex, ey, ew, eh, 0, 0);
+        d->tp->end();
+        p->drawPixmap(ex, ey, *d->vertPaintBuffer, 0, 0, ew, eh);
     }
-    if ( d->paintBuffer->width() < visibleWidth() )
-        d->paintBuffer->resize(visibleWidth(),PAINT_BUFFER_HEIGHT);
+    else {
+        if ( d->paintBuffer->width() < visibleWidth() )
+            d->paintBuffer->resize(visibleWidth(),PAINT_BUFFER_HEIGHT);
 
-    int py=0;
-    while (py < eh) {
-        int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;
-        d->tp->begin(d->paintBuffer);
-        d->tp->translate(-ex, -ey-py);
-        d->tp->fillRect(ex, ey+py, ew, ph, palette().normal().brush(QColorGroup::Base));
-        m_part->xmlDocImpl()->renderer()->print(d->tp, ex, ey+py, ew, ph, 0, 0);
+        int py=0;
+        while (py < eh) {
+            int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;
+            d->tp->begin(d->paintBuffer);
+            d->tp->translate(-ex, -ey-py);
+            d->tp->fillRect(ex, ey+py, ew, ph, palette().normal().brush(QColorGroup::Base));
+            m_part->xmlDocImpl()->renderer()->print(d->tp, ex, ey+py, ew, ph, 0, 0);
 #ifdef BOX_DEBUG
-        if (m_part->xmlDocImpl()->focusNode())
-        {
-            d->tp->setBrush(Qt::NoBrush);
-            d->tp->drawRect(m_part->xmlDocImpl()->focusNode()->getRect());
-        }
+            if (m_part->xmlDocImpl()->focusNode())
+            {
+                d->tp->setBrush(Qt::NoBrush);
+                d->tp->drawRect(m_part->xmlDocImpl()->focusNode()->getRect());
+            }
 #endif
-        d->tp->end();
+            d->tp->end();
 
-        p->drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph);
-        py += PAINT_BUFFER_HEIGHT;
+            p->drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph);
+            py += PAINT_BUFFER_HEIGHT;
+        }
     }
     khtml::DrawContentsEvent event( p, ex, ey, ew, eh );
     QApplication::sendEvent( m_part, &event );
@@ -623,7 +645,9 @@ void KHTMLView::keyPressEvent( QKeyEvent
     }
 
     int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
-    static int timings [][2] = { {100,1}, {50,1}, {30,1}, {20,1}, {20,2}, {20,4}, {20,6}, {0,0} };
+    static const struct { int msec, pixels; } timings [] = { 
+        {100,1}, {50,1}, {30,1}, {20,1}, {20,2}, {20,4}, {20,6}, {0,0} 
+    };
     if (_ke->state() & Qt::ShiftButton)
       switch(_ke->key())
         {
@@ -636,31 +660,89 @@ void KHTMLView::keyPressEvent( QKeyEvent
 
         case Key_Down:
         case Key_J:
-            if (!d->scrollTimerId) {
+            if (!d->scrollTimerId || 
+                d->scrollDirection == KHTMLViewPrivate::ScrollLeft || 
+                d->scrollDirection == KHTMLViewPrivate::ScrollRight) {
                 d->scrollTiming = 2;
-                d->scrollBy = timings[d->scrollTiming][1];
+                d->scrollBy = timings[d->scrollTiming].pixels;
+                d->scrollDirection = KHTMLViewPrivate::ScrollDown;
                 scrollBy( 0, d->scrollBy );
-                d->scrollTimerId = startTimer(timings[d->scrollTiming][0]);
-            } else if (timings[d->scrollTiming+1][0]) {
-                d->scrollBy = timings[++d->scrollTiming][1];
+            } else if (d->scrollDirection == KHTMLViewPrivate::ScrollDown && 
+                    timings[d->scrollTiming+1].msec) {
+                d->scrollBy = timings[++d->scrollTiming].pixels;
                 scrollBy( 0, d->scrollBy );
-                killTimer(d->scrollTimerId);
-                d->scrollTimerId = startTimer(timings[d->scrollTiming][0]);
+            } else if (d->scrollDirection == KHTMLViewPrivate::ScrollUp) {
+                if (d->scrollTiming)
+                    d->scrollBy = timings[--d->scrollTiming].pixels;
+                else
+                    d->scrollDirection = KHTMLViewPrivate::ScrollDown;
             }
+            NEWSCROLLTIMER(startTimer(timings[d->scrollTiming].msec));
             break;
 
         case Key_Up:
         case Key_K:
-            if (d->scrollTimerId)
-                if (d->scrollTiming) {
-                    d->scrollBy = timings[--d->scrollTiming][1];
-                    killTimer(d->scrollTimerId);
-                    d->scrollTimerId = startTimer(timings[d->scrollTiming][0]);
-                } else {
-                    killTimer(d->scrollTimerId);
-                    d->scrollTimerId = 0;
-                }
+            if (!d->scrollTimerId || 
+                d->scrollDirection == KHTMLViewPrivate::ScrollLeft || 
+                d->scrollDirection == KHTMLViewPrivate::ScrollRight) {
+                d->scrollTiming = 2;
+                d->scrollBy = timings[d->scrollTiming].pixels;
+                d->scrollDirection = KHTMLViewPrivate::ScrollUp;
+            } else if (d->scrollDirection == KHTMLViewPrivate::ScrollUp && 
+                    timings[d->scrollTiming+1].msec) {
+                d->scrollBy = timings[++d->scrollTiming].pixels;
+                scrollBy( 0, -d->scrollBy );
+            } else if (d->scrollDirection == KHTMLViewPrivate::ScrollDown) {
+                if (d->scrollTiming)
+                    d->scrollBy = timings[--d->scrollTiming].pixels;
+                else
+                    d->scrollDirection = KHTMLViewPrivate::ScrollUp;
+            }
+            NEWSCROLLTIMER(startTimer(timings[d->scrollTiming].msec));
+            break;
+
+        case Key_Left:
+        case Key_H:
+            if (!d->scrollTimerId || 
+                d->scrollDirection == KHTMLViewPrivate::ScrollUp || 
+                d->scrollDirection == KHTMLViewPrivate::ScrollDown) {
+                d->scrollTiming = 2;
+                d->scrollBy = timings[d->scrollTiming].pixels;
+                d->scrollDirection = KHTMLViewPrivate::ScrollLeft;
+                scrollBy( -d->scrollBy, 0 );
+            } else if (d->scrollDirection == KHTMLViewPrivate::ScrollLeft && 
+                    timings[d->scrollTiming+1].msec) {
+                d->scrollBy = timings[++d->scrollTiming].pixels;
+                scrollBy( -d->scrollBy, 0 );
+            } else if (d->scrollDirection == KHTMLViewPrivate::ScrollRight) {
+                if (d->scrollTiming)
+                    d->scrollBy = timings[--d->scrollTiming].pixels;
+                else
+                    d->scrollDirection = KHTMLViewPrivate::ScrollLeft;
+            }
+            NEWSCROLLTIMER(startTimer(timings[d->scrollTiming].msec));
+            break;
 
+        case Key_Right:
+        case Key_L:
+            if (!d->scrollTimerId || 
+                d->scrollDirection == KHTMLViewPrivate::ScrollUp || 
+                d->scrollDirection == KHTMLViewPrivate::ScrollDown) {
+                d->scrollTiming = 2;
+                d->scrollBy = timings[d->scrollTiming].pixels;
+                d->scrollDirection = KHTMLViewPrivate::ScrollRight;
+                scrollBy( d->scrollBy, 0 );
+            } else if (d->scrollDirection == KHTMLViewPrivate::ScrollRight && 
+                    timings[d->scrollTiming+1].msec) {
+                d->scrollBy = timings[++d->scrollTiming].pixels;
+                scrollBy( d->scrollBy, 0 );
+            } else if (d->scrollDirection == KHTMLViewPrivate::ScrollLeft) {
+                if (d->scrollTiming)
+                    d->scrollBy = timings[--d->scrollTiming].pixels;
+                else
+                    d->scrollDirection = KHTMLViewPrivate::ScrollRight;
+            }
+            NEWSCROLLTIMER(startTimer(timings[d->scrollTiming].msec));
             break;
         }
     else
@@ -692,10 +774,8 @@ void KHTMLView::keyPressEvent( QKeyEvent
             if ( d->vmode == QScrollView::AlwaysOff )
                 _ke->accept();
             else {
-                if (d->scrollTimerId) {
-                    killTimer(d->scrollTimerId);
-                    d->scrollTimerId = 0;
-                }
+                if (d->scrollTimerId)
+                    NEWSCROLLTIMER(0);
                 scrollBy( 0, -10 );
             }
             break;
@@ -710,15 +790,21 @@ void KHTMLView::keyPressEvent( QKeyEvent
         case Key_L:
             if ( d->hmode == QScrollView::AlwaysOff )
                 _ke->accept();
-            else
+            else {
+                if (d->scrollTimerId)
+                    NEWSCROLLTIMER(0);
                 scrollBy( 10, 0 );
+            }
             break;
         case Key_Left:
         case Key_H:
             if ( d->hmode == QScrollView::AlwaysOff )
                 _ke->accept();
-            else
+            else {
+                if (d->scrollTimerId)
+                    NEWSCROLLTIMER(0);
                 scrollBy( -10, 0 );
+            }
             break;
         case Key_Enter:
         case Key_Return:
@@ -744,7 +830,15 @@ void KHTMLView::keyPressEvent( QKeyEvent
             else
                 setContentsPos( 0, contentsHeight() - visibleHeight() );
             break;
+        case Key_Shift:
+            // what are you doing here?
+	    _ke->ignore();
+            return;
         default:
+            if (d->scrollTimerId) {
+                killTimer(d->scrollTimerId);
+                d->scrollTimerId = 0;
+            }
 	    _ke->ignore();
             return;
         }
@@ -1512,12 +1606,32 @@ void KHTMLView::timerEvent ( QTimerEvent
 {
 //    kdDebug() << "timer event " << e->timerId() << endl;
     if (e->timerId() == d->scrollTimerId) {
-        if (contentsY() + visibleHeight () >= contentsHeight()) {
-            kdDebug() << "timer event killing timer" << endl;
-            killTimer(d->scrollTimerId);
-            d->scrollTimerId = 0;
-        } else
-            scrollBy( 0, d->scrollBy );
+        switch (d->scrollDirection) {
+            case KHTMLViewPrivate::ScrollDown:
+                if (contentsY() + visibleHeight () >= contentsHeight())
+                    NEWSCROLLTIMER(0)
+                else
+                    scrollBy( 0, d->scrollBy );
+                break;
+            case KHTMLViewPrivate::ScrollUp:
+                if (contentsY() <= 0)
+                    NEWSCROLLTIMER(0)
+                else
+                    scrollBy( 0, -d->scrollBy );
+                break;
+            case KHTMLViewPrivate::ScrollRight:
+                if (contentsX() + visibleWidth () >= contentsWidth())
+                    NEWSCROLLTIMER(0)
+                else
+                    scrollBy( d->scrollBy, 0 );
+                break;
+            case KHTMLViewPrivate::ScrollLeft:
+                if (contentsX() <= 0)
+                    NEWSCROLLTIMER(0)
+                else
+                    scrollBy( -d->scrollBy, 0 );
+                break;
+        }
         return;
     }
     if (e->timerId()==d->timerId)


More information about the kfm-devel mailing list