00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "khtmlview.h"
00030
00031 #include "khtmlview.moc"
00032
00033 #include "khtml_part.h"
00034 #include "khtml_events.h"
00035 #ifdef Q_WS_X11
00036 #include <qx11info_x11.h>
00037 #endif
00038
00039 #include "html/html_documentimpl.h"
00040 #include "html/html_inlineimpl.h"
00041 #include "html/html_formimpl.h"
00042 #include "html/htmltokenizer.h"
00043 #include "editing/editor.h"
00044 #include "rendering/render_arena.h"
00045 #include "rendering/render_canvas.h"
00046 #include "rendering/render_frames.h"
00047 #include "rendering/render_replaced.h"
00048 #include "rendering/render_form.h"
00049 #include "rendering/render_layer.h"
00050 #include "rendering/render_line.h"
00051 #include "rendering/render_table.h"
00052
00053 #define protected public
00054 #include "rendering/render_text.h"
00055 #undef protected
00056 #include "xml/dom2_eventsimpl.h"
00057 #include "css/cssstyleselector.h"
00058 #include "css/csshelper.h"
00059 #include "misc/htmlhashes.h"
00060 #include "misc/helper.h"
00061 #include "misc/loader.h"
00062 #include "khtml_settings.h"
00063 #include "khtml_printsettings.h"
00064
00065 #include "khtmlpart_p.h"
00066
00067 #include <kcursor.h>
00068 #include <kdebug.h>
00069 #include <kglobalsettings.h>
00070 #include <kdialog.h>
00071 #include <kiconloader.h>
00072 #include <klocale.h>
00073 #include <knotification.h>
00074 #include <kdeprintdialog.h>
00075 #include <kconfig.h>
00076 #include <kstandarddirs.h>
00077 #include <kstandardshortcut.h>
00078 #include <kstringhandler.h>
00079 #include <kconfiggroup.h>
00080
00081 #include <QtGui/QBitmap>
00082 #include <QtGui/QLabel>
00083 #include <QtCore/QObject>
00084 #include <QtGui/QPainter>
00085 #include <QtCore/QHash>
00086 #include <QtGui/QToolTip>
00087 #include <QtCore/QString>
00088 #include <QtGui/QTextDocument>
00089 #include <QtCore/QTimer>
00090 #include <QtCore/QAbstractEventDispatcher>
00091 #include <QtCore/QVector>
00092 #include <QtGui/QAbstractScrollArea>
00093 #include <QtGui/QPrinter>
00094 #include <QtGui/QPrintDialog>
00095
00096
00097
00098 #include <limits.h>
00099 #ifdef Q_WS_X11
00100 #include <X11/Xlib.h>
00101 #include <fixx11h.h>
00102 #elif defined(Q_WS_WIN)
00103 #include <windows.h>
00104 #endif
00105
00106 #if 0
00107 namespace khtml {
00108 void dumpLineBoxes(RenderFlow *flow);
00109 }
00110 #endif
00111
00112 using namespace DOM;
00113 using namespace khtml;
00114
00115 #ifndef NDEBUG
00116 static const int sFirstLayoutDelay = 760;
00117 static const int sParsingLayoutsInterval = 420;
00118 static const int sLayoutAttemptDelay = 400;
00119 #else
00120 static const int sFirstLayoutDelay = 540;
00121 static const int sParsingLayoutsInterval = 360;
00122 static const int sLayoutAttemptDelay = 340;
00123 #endif
00124 static const int sLayoutAttemptIncrement = 20;
00125 static const int sParsingLayoutsIncrement = 60;
00126
00127 static const int sSmoothScrollTime = 140;
00128 static const int sSmoothScrollTick = 14;
00129 static const int sSmoothScrollMinStaticPixels = 320*200;
00130
00131 static const int sMaxMissedDeadlines = 12;
00132 static const int sWayTooMany = -1;
00133
00134 class KHTMLViewPrivate {
00135 friend class KHTMLView;
00136 public:
00137
00138 enum PseudoFocusNodes {
00139 PFNone,
00140 PFTop,
00141 PFBottom
00142 };
00143
00144 enum StaticBackgroundState {
00145 SBNone = 0,
00146 SBPartial,
00147 SBFull
00148 };
00149
00150 enum CompletedState {
00151 CSNone = 0,
00152 CSFull,
00153 CSActionPending
00154 };
00155
00156 KHTMLViewPrivate(KHTMLView* v)
00157 : underMouse( 0 ), underMouseNonShared( 0 ), oldUnderMouse( 0 )
00158 {
00159 postponed_autorepeat = NULL;
00160 scrollingFromWheelTimerId = 0;
00161 smoothScrollMode = KHTMLView::SSMWhenEfficient;
00162
00163 reset();
00164 vpolicy = Qt::ScrollBarAsNeeded;
00165 hpolicy = Qt::ScrollBarAsNeeded;
00166 formCompletions=0;
00167 prevScrollbarVisible = true;
00168
00169 possibleTripleClick = false;
00170 emitCompletedAfterRepaint = CSNone;
00171 cursorIconWidget = 0;
00172 cursorIconType = KHTMLView::LINK_NORMAL;
00173 m_mouseScrollTimer = 0;
00174 m_mouseScrollIndicator = 0;
00175 contentsX = 0;
00176 contentsY = 0;
00177 view = v;
00178 }
00179 ~KHTMLViewPrivate()
00180 {
00181 delete formCompletions;
00182 delete postponed_autorepeat;
00183 if (underMouse)
00184 underMouse->deref();
00185 if (underMouseNonShared)
00186 underMouseNonShared->deref();
00187 if (oldUnderMouse)
00188 oldUnderMouse->deref();
00189
00190 delete cursorIconWidget;
00191 delete m_mouseScrollTimer;
00192 delete m_mouseScrollIndicator;
00193 }
00194 void reset()
00195 {
00196 if (underMouse)
00197 underMouse->deref();
00198 underMouse = 0;
00199 if (underMouseNonShared)
00200 underMouseNonShared->deref();
00201 underMouseNonShared = 0;
00202 if (oldUnderMouse)
00203 oldUnderMouse->deref();
00204 oldUnderMouse = 0;
00205 linkPressed = false;
00206 staticWidget = SBNone;
00207 fixedObjectsCount = 0;
00208 staticObjectsCount = 0;
00209 tabMovePending = false;
00210 lastTabbingDirection = true;
00211 pseudoFocusNode = PFNone;
00212 zoomLevel = 100;
00213 #ifndef KHTML_NO_SCROLLBARS
00214
00215
00216
00217
00218 #else
00219 vpolicy = ScrollBarAlwaysOff;
00220 hpolicy = ScrollBarAlwaysOff;
00221 #endif
00222 scrollBarMoved = false;
00223 contentsMoving = false;
00224 ignoreWheelEvents = false;
00225 scrollingFromWheel = QPoint(-1,-1);
00226 borderX = 30;
00227 borderY = 30;
00228 dx = dy = ddx = ddy = rdx = rdy = dddx = dddy = 0;
00229 paged = false;
00230 clickX = -1;
00231 clickY = -1;
00232 clickCount = 0;
00233 isDoubleClick = false;
00234 scrollingSelf = false;
00235 delete postponed_autorepeat;
00236 postponed_autorepeat = NULL;
00237 layoutTimerId = 0;
00238 repaintTimerId = 0;
00239 scrollTimerId = 0;
00240 scrollSuspended = false;
00241 scrollSuspendPreActivate = false;
00242 smoothScrolling = false;
00243 smoothScrollModeIsDefault = true;
00244 shouldSmoothScroll = false;
00245 smoothScrollMissedDeadlines = 0;
00246 hasFrameset = false;
00247 complete = false;
00248 firstLayoutPending = true;
00249 firstRepaintPending = true;
00250 needsFullRepaint = true;
00251 dirtyLayout = false;
00252 layoutSchedulingEnabled = true;
00253 painting = false;
00254 layoutCounter = 0;
00255 layoutAttemptCounter = 0;
00256 scheduledLayoutCounter = 0;
00257 updateRegion = QRegion();
00258 m_dialogsAllowed = true;
00259 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00260 typeAheadActivated = false;
00261 #endif // KHTML_NO_TYPE_AHEAD_FIND
00262 accessKeysActivated = false;
00263 accessKeysPreActivate = false;
00264
00265
00266
00267
00268 KHTMLGlobal::ref();
00269 accessKeysEnabled = KHTMLGlobal::defaultHTMLSettings()->accessKeysEnabled();
00270 KHTMLGlobal::deref();
00271
00272 emitCompletedAfterRepaint = CSNone;
00273 m_mouseEventsTarget = 0;
00274 m_clipHolder = 0;
00275 }
00276 void newScrollTimer(QWidget *view, int tid)
00277 {
00278
00279 view->killTimer(scrollTimerId);
00280 scrollTimerId = tid;
00281 scrollSuspended = false;
00282 }
00283 enum ScrollDirection { ScrollLeft, ScrollRight, ScrollUp, ScrollDown };
00284
00285 void adjustScroller(QWidget *view, ScrollDirection direction, ScrollDirection oppositedir)
00286 {
00287 static const struct { int msec, pixels; } timings [] = {
00288 {320,1}, {224,1}, {160,1}, {112,1}, {80,1}, {56,1}, {40,1},
00289 {28,1}, {20,1}, {20,2}, {20,3}, {20,4}, {20,6}, {20,8}, {0,0}
00290 };
00291 if (!scrollTimerId ||
00292 (static_cast<int>(scrollDirection) != direction &&
00293 (static_cast<int>(scrollDirection) != oppositedir || scrollSuspended))) {
00294 scrollTiming = 6;
00295 scrollBy = timings[scrollTiming].pixels;
00296 scrollDirection = direction;
00297 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00298 } else if (scrollDirection == direction &&
00299 timings[scrollTiming+1].msec && !scrollSuspended) {
00300 scrollBy = timings[++scrollTiming].pixels;
00301 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00302 } else if (scrollDirection == oppositedir) {
00303 if (scrollTiming) {
00304 scrollBy = timings[--scrollTiming].pixels;
00305 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00306 }
00307 }
00308 scrollSuspended = false;
00309 }
00310
00311 bool haveZoom() const { return zoomLevel != 100; }
00312
00313 void startScrolling()
00314 {
00315 smoothScrolling = true;
00316 smoothScrollTimer.start(sSmoothScrollTick);
00317 shouldSmoothScroll = false;
00318 }
00319
00320 void stopScrolling()
00321 {
00322 smoothScrollTimer.stop();
00323 dx = dy = 0;
00324 ddx = ddy = 0;
00325 rdx = rdy = 0;
00326 dddx = dddy = 0;
00327 updateContentsXY();
00328 smoothScrolling = false;
00329 shouldSmoothScroll = false;
00330 }
00331
00332 void updateContentsXY()
00333 {
00334 contentsX = QApplication::isRightToLeft() ?
00335 view->horizontalScrollBar()->maximum()-view->horizontalScrollBar()->value() : view->horizontalScrollBar()->value();
00336 contentsY = view->verticalScrollBar()->value();
00337 }
00338
00339 void scrollExternalWidgets(int dx, int dy)
00340 {
00341 if (visibleWidgets.isEmpty())
00342 return;
00343
00344 QHashIterator<void*, QWidget*> it(visibleWidgets);
00345 while (it.hasNext()) {
00346 it.next();
00347 it.value()->move( it.value()->pos() + QPoint(dx, dy) );
00348 }
00349 }
00350
00351 NodeImpl *underMouse;
00352 NodeImpl *underMouseNonShared;
00353 NodeImpl *oldUnderMouse;
00354
00355
00356
00357 bool tabMovePending:1;
00358 bool lastTabbingDirection:1;
00359 PseudoFocusNodes pseudoFocusNode:3;
00360 bool scrollBarMoved:1;
00361 bool contentsMoving:1;
00362
00363 Qt::ScrollBarPolicy vpolicy;
00364 Qt::ScrollBarPolicy hpolicy;
00365 bool prevScrollbarVisible:1;
00366 bool linkPressed:1;
00367 bool ignoreWheelEvents:1;
00368 StaticBackgroundState staticWidget: 3;
00369 int staticObjectsCount;
00370 int fixedObjectsCount;
00371
00372 int zoomLevel;
00373 int borderX, borderY;
00374 int dx, dy, ddx, ddy, rdx, rdy, dddx, dddy;
00375 KConfig *formCompletions;
00376
00377 int clickX, clickY, clickCount;
00378 bool isDoubleClick;
00379
00380 bool paged;
00381
00382 bool scrollingSelf;
00383 int contentsX, contentsY;
00384 int layoutTimerId;
00385 QKeyEvent* postponed_autorepeat;
00386
00387 int repaintTimerId;
00388 int scrollTimerId;
00389 int scrollTiming;
00390 int scrollBy;
00391 ScrollDirection scrollDirection :3;
00392 bool scrollSuspended :1;
00393 bool scrollSuspendPreActivate :1;
00394 KHTMLView::SmoothScrollingMode smoothScrollMode :3;
00395 bool smoothScrolling :1;
00396 bool smoothScrollModeIsDefault :1;
00397 bool shouldSmoothScroll :1;
00398 bool hasFrameset :1;
00399 bool complete :1;
00400 bool firstLayoutPending :1;
00401 bool firstRepaintPending :1;
00402 bool layoutSchedulingEnabled :1;
00403 bool needsFullRepaint :1;
00404 bool painting :1;
00405 bool possibleTripleClick :1;
00406 bool dirtyLayout :1;
00407 bool m_dialogsAllowed :1;
00408 short smoothScrollMissedDeadlines;
00409 int layoutCounter;
00410 int layoutAttemptCounter;
00411 int scheduledLayoutCounter;
00412 QRegion updateRegion;
00413 QTimer smoothScrollTimer;
00414 QTime smoothScrollStopwatch;
00415 QHash<void*, QWidget*> visibleWidgets;
00416 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00417 QString findString;
00418 QTimer timer;
00419 bool findLinksOnly;
00420 bool typeAheadActivated;
00421 #endif // KHTML_NO_TYPE_AHEAD_FIND
00422 bool accessKeysEnabled;
00423 bool accessKeysActivated;
00424 bool accessKeysPreActivate;
00425 CompletedState emitCompletedAfterRepaint;
00426
00427 QLabel* cursorIconWidget;
00428 KHTMLView::LinkCursor cursorIconType;
00429
00430
00431 short m_mouseScroll_byX;
00432 short m_mouseScroll_byY;
00433 QPoint scrollingFromWheel;
00434 int scrollingFromWheelTimerId;
00435 QTimer *m_mouseScrollTimer;
00436 QWidget *m_mouseScrollIndicator;
00437 QPointer<QWidget> m_mouseEventsTarget;
00438 QStack<QRegion>* m_clipHolder;
00439 KHTMLView* view;
00440 };
00441
00442 #ifndef QT_NO_TOOLTIP
00443
00453 static bool findImageMapRect(HTMLImageElementImpl *img, const QPoint &scrollOfs,
00454 const QPoint &p, QRect &r, QString &s)
00455 {
00456 HTMLMapElementImpl* map;
00457 if (img && img->document()->isHTMLDocument() &&
00458 (map = static_cast<HTMLDocumentImpl*>(img->document())->getMap(img->imageMap()))) {
00459 RenderObject::NodeInfo info(true, false);
00460 RenderObject *rend = img->renderer();
00461 int ax, ay;
00462 if (!rend || !rend->absolutePosition(ax, ay))
00463 return false;
00464
00465 bool inside = map->mapMouseEvent(p.x() - ax + scrollOfs.x(),
00466 p.y() - ay + scrollOfs.y(), rend->contentWidth(),
00467 rend->contentHeight(), info);
00468 if (inside && info.URLElement()) {
00469 HTMLAreaElementImpl *area = static_cast<HTMLAreaElementImpl *>(info.URLElement());
00470 Q_ASSERT(area->id() == ID_AREA);
00471 s = area->getAttribute(ATTR_TITLE).string();
00472 QRegion reg = area->cachedRegion();
00473 if (!s.isEmpty() && !reg.isEmpty()) {
00474 r = reg.boundingRect();
00475 r.translate(ax, ay);
00476 return true;
00477 }
00478 }
00479 }
00480 return false;
00481 }
00482
00483 bool KHTMLView::event( QEvent* e )
00484 {
00485 switch ( e->type() ) {
00486 case QEvent::ToolTip: {
00487 QHelpEvent *he = static_cast<QHelpEvent*>(e);
00488 QPoint p = he->pos();
00489
00490 DOM::NodeImpl *node = d->underMouseNonShared;
00491 QRect region;
00492 while ( node ) {
00493 if ( node->isElementNode() ) {
00494 DOM::ElementImpl *e = static_cast<DOM::ElementImpl*>( node );
00495 QRect r;
00496 QString s;
00497 bool found = false;
00498
00499
00500 if (e->id() == ID_IMG && !e->getAttribute( ATTR_USEMAP ).isEmpty()) {
00501 found = findImageMapRect(static_cast<HTMLImageElementImpl *>(e),
00502 viewportToContents(QPoint(0, 0)), p, r, s);
00503 }
00504 if (!found) {
00505 s = e->getAttribute( ATTR_TITLE ).string();
00506 r = node->getRect();
00507 }
00508 region |= QRect( contentsToViewport( r.topLeft() ), r.size() );
00509 if ( !s.isEmpty() ) {
00510 QToolTip::showText( he->globalPos(),
00511 Qt::convertFromPlainText( s, Qt::WhiteSpaceNormal ),
00512 widget(), region );
00513 break;
00514 }
00515 }
00516 node = node->parentNode();
00517 }
00518
00519
00520
00521 return false;
00522 }
00523
00524 case QEvent::DragEnter:
00525 case QEvent::DragMove:
00526 case QEvent::DragLeave:
00527 case QEvent::Drop:
00528
00529
00530
00531
00532
00533
00534
00535
00536 return QWidget::event(e);
00537 case QEvent::StyleChange:
00538 case QEvent::LayoutRequest: {
00539 updateScrollBars();
00540 return QAbstractScrollArea::event(e);
00541 }
00542 case QEvent::PaletteChange:
00543 slotPaletteChanged();
00544 return QScrollArea::event(e);
00545 default:
00546 return QScrollArea::event(e);
00547 }
00548 }
00549 #endif
00550
00551 KHTMLView::KHTMLView( KHTMLPart *part, QWidget *parent )
00552 : QScrollArea( parent ), d( new KHTMLViewPrivate( this ) )
00553 {
00554 m_medium = "screen";
00555
00556 m_part = part;
00557
00558 QScrollArea::setVerticalScrollBarPolicy(d->vpolicy);
00559 QScrollArea::setHorizontalScrollBarPolicy(d->hpolicy);
00560
00561 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00562 connect(&d->timer, SIGNAL(timeout()), this, SLOT(findTimeout()));
00563 #endif // KHTML_NO_TYPE_AHEAD_FIND
00564
00565 init();
00566 widget()->setMouseTracking(true);
00567 }
00568
00569 KHTMLView::~KHTMLView()
00570 {
00571 closeChildDialogs();
00572 if (m_part)
00573 {
00574 DOM::DocumentImpl *doc = m_part->xmlDocImpl();
00575 if (doc)
00576 doc->detach();
00577 }
00578 delete d;
00579 }
00580
00581 void KHTMLView::setPart(KHTMLPart *part)
00582 {
00583 assert(part && !m_part);
00584 m_part = part;
00585 }
00586
00587 void KHTMLView::init()
00588 {
00589
00590
00591 setFrameStyle(QFrame::NoFrame);
00592 setFocusPolicy(Qt::StrongFocus);
00593 viewport()->setFocusProxy(this);
00594
00595 _marginWidth = -1;
00596 _marginHeight = -1;
00597 _width = 0;
00598 _height = 0;
00599
00600 installEventFilter(this);
00601
00602 setAcceptDrops(true);
00603 if (!widget())
00604 setWidget( new QWidget(this) );
00605 widget()->setAttribute( Qt::WA_NoSystemBackground );
00606
00607
00608
00609
00610
00611 widget()->setAttribute( Qt::WA_OpaquePaintEvent );
00612
00613 verticalScrollBar()->setCursor( Qt::ArrowCursor );
00614 horizontalScrollBar()->setCursor( Qt::ArrowCursor );
00615
00616 connect(&d->smoothScrollTimer, SIGNAL(timeout()), this, SLOT(scrollTick()));
00617 }
00618
00619 void KHTMLView::resizeContentsToViewport()
00620 {
00621 QSize s = viewport()->size();
00622 resizeContents(s.width(), s.height());
00623 }
00624
00625
00626
00627 void KHTMLView::clear()
00628 {
00629 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00630 if( d->typeAheadActivated )
00631 findTimeout();
00632 #endif
00633 if (d->accessKeysEnabled && d->accessKeysActivated)
00634 accessKeysTimeout();
00635 viewport()->unsetCursor();
00636 if ( d->cursorIconWidget )
00637 d->cursorIconWidget->hide();
00638 if (d->smoothScrolling)
00639 d->stopScrolling();
00640 d->reset();
00641 QAbstractEventDispatcher::instance()->unregisterTimers(this);
00642 emit cleared();
00643
00644 QScrollArea::setHorizontalScrollBarPolicy(d->hpolicy);
00645 QScrollArea::setVerticalScrollBarPolicy(d->vpolicy);
00646 verticalScrollBar()->setEnabled( false );
00647 horizontalScrollBar()->setEnabled( false );
00648
00649 }
00650
00651 void KHTMLView::hideEvent(QHideEvent* e)
00652 {
00653 QScrollArea::hideEvent(e);
00654 if ( m_part && m_part->xmlDocImpl() )
00655 m_part->xmlDocImpl()->docLoader()->pauseAnimations();
00656 }
00657
00658 void KHTMLView::showEvent(QShowEvent* e)
00659 {
00660 QScrollArea::showEvent(e);
00661 if ( m_part && m_part->xmlDocImpl() )
00662 m_part->xmlDocImpl()->docLoader()->resumeAnimations();
00663 }
00664
00665 void KHTMLView::setMouseEventsTarget( QWidget* w )
00666 {
00667 d->m_mouseEventsTarget = w;
00668 }
00669
00670 QWidget* KHTMLView::mouseEventsTarget() const
00671 {
00672 return d->m_mouseEventsTarget;
00673 }
00674
00675 void KHTMLView::setClipHolder( QStack<QRegion>* ch )
00676 {
00677 d->m_clipHolder = ch;
00678 }
00679
00680 QStack<QRegion>* KHTMLView::clipHolder() const
00681 {
00682 return d->m_clipHolder;
00683 }
00684
00685 int KHTMLView::contentsWidth() const
00686 {
00687 return widget() ? widget()->width() : 0;
00688 }
00689
00690 int KHTMLView::contentsHeight() const
00691 {
00692 return widget() ? widget()->height() : 0;
00693 }
00694
00695 void KHTMLView::resizeContents(int w, int h)
00696 {
00697 if (!widget())
00698 return;
00699 widget()->resize(w, h);
00700 if (!widget()->isVisible())
00701 updateScrollBars();
00702 }
00703
00704 int KHTMLView::contentsX() const
00705 {
00706 return d->contentsX;
00707 }
00708
00709 int KHTMLView::contentsY() const
00710 {
00711 return d->contentsY;
00712 }
00713
00714 int KHTMLView::visibleWidth() const
00715 {
00716 if (m_kwp->isRedirected()) {
00717
00718 if (RenderWidget* rw = m_kwp->renderWidget()) {
00719 int ret = rw->width()-rw->paddingLeft()-rw->paddingRight()-rw->borderLeft()-rw->borderRight();
00720 if (verticalScrollBar()->isVisible()) {
00721 ret -= verticalScrollBar()->sizeHint().width();
00722 ret = qMax(0, ret);
00723 }
00724 return ret;
00725 }
00726 }
00727 return viewport()->width();
00728 }
00729
00730 int KHTMLView::visibleHeight() const
00731 {
00732 if (m_kwp->isRedirected()) {
00733
00734 if (RenderWidget* rw = m_kwp->renderWidget()) {
00735 int ret = rw->height()-rw->paddingBottom()-rw->paddingTop()-rw->borderTop()-rw->borderBottom();
00736 if (horizontalScrollBar()->isVisible()) {
00737 ret -= horizontalScrollBar()->sizeHint().height();
00738 ret = qMax(0, ret);
00739 }
00740 return ret;
00741 }
00742 }
00743 return viewport()->height();
00744 }
00745
00746 void KHTMLView::setContentsPos( int x, int y)
00747 {
00748 horizontalScrollBar()->setValue( QApplication::isRightToLeft() ?
00749 horizontalScrollBar()->maximum()-x : x );
00750 verticalScrollBar()->setValue( y );
00751 }
00752
00753 void KHTMLView::scrollBy(int x, int y)
00754 {
00755 if (d->scrollTimerId)
00756 d->newScrollTimer(this, 0);
00757 horizontalScrollBar()->setValue( horizontalScrollBar()->value()+x );
00758 verticalScrollBar()->setValue( verticalScrollBar()->value()+y );
00759 }
00760
00761 QPoint KHTMLView::contentsToViewport(const QPoint& p) const
00762 {
00763 return QPoint(p.x()-contentsX(), p.y()-contentsY());
00764 }
00765
00766 void KHTMLView::contentsToViewport(int x, int y, int& cx, int& cy) const
00767 {
00768 QPoint p(x,y);
00769 p = contentsToViewport(p);
00770 cx = p.x();
00771 cy = p.y();
00772 }
00773
00774 QPoint KHTMLView::viewportToContents(const QPoint& p) const
00775 {
00776 return QPoint(p.x()+contentsX(), p.y()+contentsY());
00777 }
00778
00779 void KHTMLView::viewportToContents(int x, int y, int& cx, int& cy) const
00780 {
00781 QPoint p(x,y);
00782 p = viewportToContents(p);
00783 cx = p.x();
00784 cy = p.y();
00785 }
00786
00787 void KHTMLView::updateContents(int x, int y, int w, int h)
00788 {
00789 applyTransforms(x, y, w, h);
00790 if (m_kwp->isRedirected()) {
00791 QPoint off = m_kwp->absolutePos();
00792 KHTMLView* pview = m_part->parentPart()->view();
00793 pview->updateContents(x+off.x(), y+off.y(), w, h);
00794 } else
00795 widget()->update(x, y, w, h);
00796 }
00797
00798 void KHTMLView::updateContents( const QRect& r )
00799 {
00800 updateContents( r.x(), r.y(), r.width(), r.height() );
00801 }
00802
00803 void KHTMLView::repaintContents(int x, int y, int w, int h)
00804 {
00805 applyTransforms(x, y, w, h);
00806 if (m_kwp->isRedirected()) {
00807 QPoint off = m_kwp->absolutePos();
00808 KHTMLView* pview = m_part->parentPart()->view();
00809 pview->repaintContents(x+off.x(), y+off.y(), w, h);
00810 } else
00811 widget()->repaint(x, y, w, h);
00812 }
00813
00814 void KHTMLView::repaintContents( const QRect& r )
00815 {
00816 repaintContents( r.x(), r.y(), r.width(), r.height() );
00817 }
00818
00819 void KHTMLView::applyTransforms( int& x, int& y, int& w, int& h) const
00820 {
00821 if (d->haveZoom()) {
00822 const int z = d->zoomLevel;
00823 x = x*z/100;
00824 y = y*z/100;
00825 w = w*z/100;
00826 h = h*z/100;
00827 }
00828 x -= contentsX();
00829 y -= contentsY();
00830 }
00831
00832 void KHTMLView::revertTransforms( int& x, int& y, int& w, int& h) const
00833 {
00834 x += contentsX();
00835 y += contentsY();
00836 if (d->haveZoom()) {
00837 const int z = d->zoomLevel;
00838 x = x*100/z;
00839 y = y*100/z;
00840 w = w*100/z;
00841 h = h*100/z;
00842 }
00843 }
00844
00845 void KHTMLView::revertTransforms( int& x, int& y ) const
00846 {
00847 int dummy = 0;
00848 revertTransforms(x, y, dummy, dummy);
00849 }
00850
00851 void KHTMLView::resizeEvent (QResizeEvent* )
00852 {
00853 updateScrollBars();
00854
00855
00856 if (!m_part->xmlDocImpl())
00857 resizeContentsToViewport();
00858
00859
00860 if (m_part->xmlDocImpl() && m_part->xmlDocImpl()->styleSelector()->affectedByViewportChange()) {
00861 m_part->xmlDocImpl()->updateStyleSelector();
00862 }
00863
00864 if (d->layoutSchedulingEnabled)
00865 layout();
00866
00867 QApplication::sendPostedEvents(viewport(), QEvent::Paint);
00868
00869 if ( m_part && m_part->xmlDocImpl() ) {
00870 if (m_part->parentPart()) {
00871
00872 khtml::ChildFrame *cf = m_part->parentPart()->frame( m_part );
00873 cf->m_partContainerElement->postResizeEvent();
00874 } else {
00875
00876 HTMLPartContainerElementImpl::sendPostedResizeEvents();
00877 m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false );
00878 }
00879 }
00880 }
00881
00882 void KHTMLView::paintEvent( QPaintEvent *e )
00883 {
00884 QPainter p(widget());
00885
00886 QRect r = e->rect();
00887 QRect v(contentsX(), contentsY(), visibleWidth(), visibleHeight());
00888 QPoint off(contentsX(),contentsY());
00889 p.translate(-off);
00890 r.translate(off);
00891
00892 r = r.intersect(v);
00893
00894 if (!r.isValid() || r.isEmpty()) return;
00895
00896 if (d->haveZoom()) {
00897 p.scale( d->zoomLevel/100., d->zoomLevel/100.);
00898
00899 r.setX(r.x()*100/d->zoomLevel);
00900 r.setY(r.y()*100/d->zoomLevel);
00901 r.setWidth(r.width()*100/d->zoomLevel);
00902 r.setHeight(r.height()*100/d->zoomLevel);
00903 r.adjust(-1,-1,1,1);
00904 }
00905 p.setClipRect(r);
00906
00907 int ex = r.x();
00908 int ey = r.y();
00909 int ew = r.width();
00910 int eh = r.height();
00911
00912 if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
00913 p.fillRect(ex, ey, ew, eh, palette().brush(QPalette::Active, QPalette::Base));
00914 return;
00915 } else if ( d->complete && static_cast<RenderCanvas*>(m_part->xmlDocImpl()->renderer())->needsLayout() ) {
00916
00917 unscheduleRelayout();
00918 layout();
00919 } else if (m_part->xmlDocImpl()->tokenizer()) {
00920 m_part->xmlDocImpl()->tokenizer()->setNormalYeldDelay();
00921 }
00922
00923 if (d->painting) {
00924 kDebug( 6000 ) << "WARNING: paintEvent reentered! ";
00925 kDebug( 6000 ) << kBacktrace();
00926 return;
00927 }
00928 d->painting = true;
00929
00930 m_part->xmlDocImpl()->renderer()->layer()->paint(&p, r);
00931
00932 if (d->hasFrameset) {
00933 NodeImpl *body = static_cast<HTMLDocumentImpl*>(m_part->xmlDocImpl())->body();
00934 if(body && body->renderer() && body->id() == ID_FRAMESET)
00935 static_cast<RenderFrameSet*>(body->renderer())->paintFrameSetRules(&p, r);
00936 else
00937 d->hasFrameset = false;
00938 }
00939
00940 khtml::DrawContentsEvent event( &p, ex, ey, ew, eh );
00941 QApplication::sendEvent( m_part, &event );
00942
00943 if (d->contentsMoving && !d->smoothScrolling && widget()->underMouse()) {
00944 QMouseEvent *tempEvent = new QMouseEvent( QEvent::MouseMove, widget()->mapFromGlobal( QCursor::pos() ),
00945 Qt::NoButton, Qt::NoButton, Qt::NoModifier );
00946 QApplication::postEvent(widget(), tempEvent);
00947 }
00948
00949 d->painting = false;
00950 d->firstRepaintPending = false;
00951 }
00952
00953 void KHTMLView::setMarginWidth(int w)
00954 {
00955
00956 _marginWidth = w;
00957 }
00958
00959 void KHTMLView::setMarginHeight(int h)
00960 {
00961
00962 _marginHeight = h;
00963 }
00964
00965 void KHTMLView::layout()
00966 {
00967 if( m_part && m_part->xmlDocImpl() ) {
00968 DOM::DocumentImpl *document = m_part->xmlDocImpl();
00969
00970 khtml::RenderCanvas* canvas = static_cast<khtml::RenderCanvas *>(document->renderer());
00971 if ( !canvas ) return;
00972
00973 d->layoutSchedulingEnabled=false;
00974 d->dirtyLayout = true;
00975
00976
00977 RenderObject * ref = 0;
00978 RenderObject* root = document->documentElement() ? document->documentElement()->renderer() : 0;
00979
00980 if (document->isHTMLDocument()) {
00981 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
00982 if(body && body->renderer() && body->id() == ID_FRAMESET) {
00983 QScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00984 QScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00985 body->renderer()->setNeedsLayout(true);
00986 d->hasFrameset = true;
00987 }
00988 else if (root)
00989 ref = (!body || root->style()->hidesOverflow()) ? root : body->renderer();
00990 } else {
00991 ref = root;
00992 }
00993 if (ref) {
00994 if( ref->style()->overflowX() == OHIDDEN ) {
00995 if (d->hpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00996 } else if (ref->style()->overflowX() == OSCROLL ) {
00997 if (d->hpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
00998 } else if (horizontalScrollBarPolicy() != d->hpolicy) {
00999 QScrollArea::setHorizontalScrollBarPolicy(d->hpolicy);
01000 }
01001 if ( ref->style()->overflowY() == OHIDDEN ) {
01002 if (d->vpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
01003 } else if (ref->style()->overflowY() == OSCROLL ) {
01004 if (d->vpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
01005 } else if (verticalScrollBarPolicy() != d->vpolicy) {
01006 QScrollArea::setVerticalScrollBarPolicy(d->vpolicy);
01007 }
01008 }
01009 d->needsFullRepaint = d->firstLayoutPending;
01010 if (_height != visibleHeight() || _width != visibleWidth()) {;
01011 d->needsFullRepaint = true;
01012 _height = visibleHeight();
01013 _width = visibleWidth();
01014 }
01015
01016 canvas->layout();
01017
01018 emit finishedLayout();
01019 if (d->firstLayoutPending) {
01020
01021
01022 d->firstLayoutPending = false;
01023 verticalScrollBar()->setEnabled( true );
01024 horizontalScrollBar()->setEnabled( true );
01025 }
01026 d->layoutCounter++;
01027
01028 if (d->accessKeysEnabled && d->accessKeysActivated) {
01029 emit hideAccessKeys();
01030 displayAccessKeys();
01031 }
01032 }
01033 else
01034 _width = visibleWidth();
01035
01036 if (d->layoutTimerId)
01037 killTimer(d->layoutTimerId);
01038 d->layoutTimerId = 0;
01039 d->layoutSchedulingEnabled=true;
01040 }
01041
01042 void KHTMLView::closeChildDialogs()
01043 {
01044 QList<QDialog *> dlgs = findChildren<QDialog *>();
01045 foreach (QDialog *dlg, dlgs)
01046 {
01047 KDialog* dlgbase = dynamic_cast<KDialog*>( dlg );
01048 if ( dlgbase ) {
01049 if ( dlgbase->testAttribute( Qt::WA_ShowModal ) ) {
01050 kDebug(6000) << "closeChildDialogs: closing dialog " << dlgbase;
01051
01052
01053 dlgbase->reject();
01054 }
01055 }
01056 else
01057 {
01058 kWarning() << "closeChildDialogs: not a KDialog! Don't use QDialogs in KDE! " << static_cast<QWidget*>(dlg);
01059 static_cast<QWidget*>(dlg)->hide();
01060 }
01061 }
01062 d->m_dialogsAllowed = false;
01063 }
01064
01065 bool KHTMLView::dialogsAllowed() {
01066 bool allowed = d->m_dialogsAllowed;
01067 KHTMLPart* p = m_part->parentPart();
01068 if (p && p->view())
01069 allowed &= p->view()->dialogsAllowed();
01070 return allowed;
01071 }
01072
01073 void KHTMLView::closeEvent( QCloseEvent* ev )
01074 {
01075 closeChildDialogs();
01076 QScrollArea::closeEvent( ev );
01077 }
01078
01079 void KHTMLView::setZoomLevel(int percent)
01080 {
01081 percent = percent < 20 ? 20 : (percent > 800 ? 800 : percent);
01082 int oldpercent = d->zoomLevel;
01083 d->zoomLevel = percent;
01084 if (percent != oldpercent) {
01085 if (d->layoutSchedulingEnabled)
01086 layout();
01087 widget()->update();
01088 }
01089 }
01090
01091 int KHTMLView::zoomLevel() const
01092 {
01093 return d->zoomLevel;
01094 }
01095
01096 void KHTMLView::setSmoothScrollingMode( SmoothScrollingMode m )
01097 {
01098 d->smoothScrollMode = m;
01099 d->smoothScrollModeIsDefault = false;
01100 if (d->smoothScrolling && !m)
01101 d->stopScrolling();
01102 }
01103
01104 void KHTMLView::setSmoothScrollingModeDefault( SmoothScrollingMode m )
01105 {
01106
01107 if (!d->smoothScrollModeIsDefault)
01108 return;
01109 d->smoothScrollMode = m;
01110 if (d->smoothScrolling && !m)
01111 d->stopScrolling();
01112 }
01113
01114 KHTMLView::SmoothScrollingMode KHTMLView::smoothScrollingMode( ) const
01115 {
01116 return d->smoothScrollMode;
01117 }
01118
01119
01120
01121
01123
01124 void KHTMLView::mousePressEvent( QMouseEvent *_mouse )
01125 {
01126 if (!m_part->xmlDocImpl()) return;
01127 if (d->possibleTripleClick && ( _mouse->button() & Qt::MouseButtonMask ) == Qt::LeftButton)
01128 {
01129 mouseDoubleClickEvent( _mouse );
01130 return;
01131 }
01132
01133 int xm = _mouse->x();
01134 int ym = _mouse->y();
01135 revertTransforms(xm, ym);
01136
01137
01138
01139 d->isDoubleClick = false;
01140
01141 DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MousePress );
01142 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
01143
01144
01145
01146 if ( (_mouse->button() == Qt::MidButton) &&
01147 !m_part->d->m_bOpenMiddleClick && !d->m_mouseScrollTimer &&
01148 mev.url.isNull() && (mev.innerNode.elementId() != ID_INPUT) ) {
01149 QPoint point = mapFromGlobal( _mouse->globalPos() );
01150
01151 d->m_mouseScroll_byX = 0;
01152 d->m_mouseScroll_byY = 0;
01153
01154 d->m_mouseScrollTimer = new QTimer( this );
01155 connect( d->m_mouseScrollTimer, SIGNAL(timeout()), this, SLOT(slotMouseScrollTimer()) );
01156
01157 if ( !d->m_mouseScrollIndicator ) {
01158 QPixmap pixmap( 48, 48 ), icon;
01159 pixmap.fill( QColor( qRgba( 127, 127, 127, 127 ) ) );
01160
01161 QPainter p( &pixmap );
01162 QStyleOption option;
01163
01164 option.rect.setRect( 16, 0, 16, 16 );
01165 QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowUp, &option, &p );
01166 option.rect.setRect( 0, 16, 16, 16 );
01167 QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowLeft, &option, &p );
01168 option.rect.setRect( 16, 32, 16, 16 );
01169 QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowDown, &option, &p );
01170 option.rect.setRect( 32, 16, 16, 16 );
01171 QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowRight, &option, &p );
01172 p.drawEllipse( 23, 23, 2, 2 );
01173
01174 d->m_mouseScrollIndicator = new QWidget( this );
01175 d->m_mouseScrollIndicator->setFixedSize( 48, 48 );
01176 QPalette palette;
01177 palette.setBrush( d->m_mouseScrollIndicator->backgroundRole(), QBrush( pixmap ) );
01178 d->m_mouseScrollIndicator->setPalette( palette );
01179 }
01180 d->m_mouseScrollIndicator->move( point.x()-24, point.y()-24 );
01181
01182 bool hasHorBar = visibleWidth() < contentsWidth();
01183 bool hasVerBar = visibleHeight() < contentsHeight();
01184
01185 KConfigGroup cg( KGlobal::config(), "HTML Settings" );
01186 if ( cg.readEntry( "ShowMouseScrollIndicator", true ) ) {
01187 d->m_mouseScrollIndicator->show();
01188 d->m_mouseScrollIndicator->unsetCursor();
01189
01190 QBitmap mask = d->m_mouseScrollIndicator->palette().brush(d->m_mouseScrollIndicator->backgroundRole()).texture().createHeuristicMask( true );
01191
01192 if ( hasHorBar && !hasVerBar ) {
01193 QBitmap bm( 16, 16 );
01194 bm.clear();
01195 QPainter painter( &mask );
01196 painter.drawPixmap( QRectF( 16, 0, bm.width(), bm.height() ), bm, bm.rect() );
01197 painter.drawPixmap( QRectF( 16, 32, bm.width(), bm.height() ), bm, bm.rect() );
01198 d->m_mouseScrollIndicator->setCursor( Qt::SizeHorCursor );
01199 }
01200 else if ( !hasHorBar && hasVerBar ) {
01201 QBitmap bm( 16, 16 );
01202 bm.clear();
01203 QPainter painter( &mask );
01204 painter.drawPixmap( QRectF( 0, 16, bm.width(), bm.height() ), bm, bm.rect() );
01205 painter.drawPixmap( QRectF( 32, 16, bm.width(), bm.height() ), bm, bm.rect() );
01206 d->m_mouseScrollIndicator->setCursor( Qt::SizeVerCursor );
01207 }
01208 else
01209 d->m_mouseScrollIndicator->setCursor( Qt::SizeAllCursor );
01210
01211 d->m_mouseScrollIndicator->setMask( mask );
01212 }
01213 else {
01214 if ( hasHorBar && !hasVerBar )
01215 viewport()->setCursor( Qt::SizeHorCursor );
01216 else if ( !hasHorBar && hasVerBar )
01217 viewport()->setCursor( Qt::SizeVerCursor );
01218 else
01219 viewport()->setCursor( Qt::SizeAllCursor );
01220 }
01221
01222 return;
01223 }
01224 else if ( d->m_mouseScrollTimer ) {
01225 delete d->m_mouseScrollTimer;
01226 d->m_mouseScrollTimer = 0;
01227
01228 if ( d->m_mouseScrollIndicator )
01229 d->m_mouseScrollIndicator->hide();
01230 }
01231
01232 if (d->clickCount > 0 &&
01233 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
01234 d->clickCount++;
01235 else {
01236 d->clickCount = 1;
01237 d->clickX = xm;
01238 d->clickY = ym;
01239 }
01240
01241 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01242 d->clickCount,_mouse,true,DOM::NodeImpl::MousePress);
01243
01244 if (!swallowEvent) {
01245 emit m_part->nodeActivated(mev.innerNode);
01246
01247 khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
01248 QApplication::sendEvent( m_part, &event );
01249
01250 }
01251 }
01252
01253 void KHTMLView::mouseDoubleClickEvent( QMouseEvent *_mouse )
01254 {
01255 if(!m_part->xmlDocImpl()) return;
01256
01257 int xm = _mouse->x();
01258 int ym = _mouse->y();
01259 revertTransforms(xm, ym);
01260
01261
01262
01263 d->isDoubleClick = true;
01264
01265 DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MouseDblClick );
01266 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
01267
01268
01269
01270 if (d->clickCount > 0 &&
01271 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
01272 d->clickCount++;
01273 else {
01274 d->clickCount = 1;
01275 d->clickX = xm;
01276 d->clickY = ym;
01277 }
01278 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01279 d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick);
01280
01281 if (!swallowEvent) {
01282 khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode, d->clickCount );
01283 QApplication::sendEvent( m_part, &event );
01284 }
01285
01286 d->possibleTripleClick=true;
01287 QTimer::singleShot(QApplication::doubleClickInterval(),this,SLOT(tripleClickTimeout()));
01288 }
01289
01290 void KHTMLView::tripleClickTimeout()
01291 {
01292 d->possibleTripleClick = false;
01293 d->clickCount = 0;
01294 }
01295
01296 static bool targetOpensNewWindow(KHTMLPart *part, QString target)
01297 {
01298 if (!target.isEmpty() && (target.toLower() != "_top") &&
01299 (target.toLower() != "_self") && (target.toLower() != "_parent")) {
01300 if (target.toLower() == "_blank")
01301 return true;
01302 else {
01303 while (part->parentPart())
01304 part = part->parentPart();
01305 if (!part->frameExists(target))
01306 return true;
01307 }
01308 }
01309 return false;
01310 }
01311
01312 void KHTMLView::mouseMoveEvent( QMouseEvent * _mouse )
01313 {
01314 if ( d->m_mouseScrollTimer ) {
01315 QPoint point = mapFromGlobal( _mouse->globalPos() );
01316
01317 int deltaX = point.x() - d->m_mouseScrollIndicator->x() - 24;
01318 int deltaY = point.y() - d->m_mouseScrollIndicator->y() - 24;
01319
01320 (deltaX > 0) ? d->m_mouseScroll_byX = 1 : d->m_mouseScroll_byX = -1;
01321 (deltaY > 0) ? d->m_mouseScroll_byY = 1 : d->m_mouseScroll_byY = -1;
01322
01323 double adX = qAbs(deltaX)/30.0;
01324 double adY = qAbs(deltaY)/30.0;
01325
01326 d->m_mouseScroll_byX = qMax(qMin(d->m_mouseScroll_byX * int(adX*adX), SHRT_MAX), SHRT_MIN);
01327 d->m_mouseScroll_byY = qMax(qMin(d->m_mouseScroll_byY * int(adY*adY), SHRT_MAX), SHRT_MIN);
01328
01329 if (d->m_mouseScroll_byX == 0 && d->m_mouseScroll_byY == 0) {
01330 d->m_mouseScrollTimer->stop();
01331 }
01332 else if (!d->m_mouseScrollTimer->isActive()) {
01333 d->m_mouseScrollTimer->start( 20 );
01334 }
01335 }
01336
01337 if(!m_part->xmlDocImpl()) return;
01338
01339 int xm = _mouse->x();
01340 int ym = _mouse->y();
01341 revertTransforms(xm, ym);
01342
01343 DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MouseMove );
01344
01345 m_part->xmlDocImpl()->prepareMouseEvent( _mouse->buttons() , xm, ym, &mev );
01346
01347
01348
01349
01350
01351 DOM::NodeImpl* target = mev.innerNode.handle();
01352 DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode();
01353
01354
01355 if (d->m_mouseEventsTarget && fn && fn->renderer() && fn->renderer()->isWidget())
01356 target = fn;
01357
01358 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,target,mev.innerNonSharedNode.handle(),false,
01359 0,_mouse,true,DOM::NodeImpl::MouseMove);
01360
01361 if (d->clickCount > 0 &&
01362 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() > QApplication::startDragDistance()) {
01363 d->clickCount = 0;
01364 }
01365
01366 khtml::RenderObject* r = target ? target->renderer() : 0;
01367 bool setCursor = true;
01368 bool forceDefault = false;
01369 if (r && r->isWidget()) {
01370 RenderWidget* rw = static_cast<RenderWidget*>(r);
01371 KHTMLWidget* kw = qobject_cast<KHTMLView*>(rw->widget())? dynamic_cast<KHTMLWidget*>(rw->widget()) : 0;
01372 if (kw && kw->m_kwp->isRedirected())
01373 setCursor = false;
01374 else if (QLineEdit* le = qobject_cast<QLineEdit*>(rw->widget())) {
01375 QList<QWidget*> wl = qFindChildren<QWidget *>( le, "KHTMLLineEditButton" );
01376
01377 foreach (QWidget*w, wl) {
01378 if (w->underMouse()) {
01379 forceDefault = true;
01380 break;
01381 }
01382 }
01383 }
01384 }
01385 khtml::RenderStyle* style = (r && r->style()) ? r->style() : 0;
01386 QCursor c;
01387 LinkCursor linkCursor = LINK_NORMAL;
01388 switch (!forceDefault ? (style ? style->cursor() : CURSOR_AUTO) : CURSOR_DEFAULT) {
01389 case CURSOR_AUTO:
01390 if ( r && r->isText() && !r->isPointInsideSelection(xm, ym, m_part->caret()) )
01391 c = QCursor(Qt::IBeamCursor);
01392 if ( mev.url.length() && m_part->settings()->changeCursor() ) {
01393 c = m_part->urlCursor();
01394 if (mev.url.string().startsWith("mailto:") && mev.url.string().indexOf('@')>0)
01395 linkCursor = LINK_MAILTO;
01396 else
01397 if ( targetOpensNewWindow( m_part, mev.target.string() ) )
01398 linkCursor = LINK_NEWWINDOW;
01399 }
01400
01401 if (r && r->isFrameSet() && !static_cast<RenderFrameSet*>(r)->noResize())
01402 c = QCursor(static_cast<RenderFrameSet*>(r)->cursorShape());
01403
01404 break;
01405 case CURSOR_CROSS:
01406 c = QCursor(Qt::CrossCursor);
01407 break;
01408 case CURSOR_POINTER:
01409 c = m_part->urlCursor();
01410 if (mev.url.string().startsWith("mailto:") && mev.url.string().indexOf('@')>0)
01411 linkCursor = LINK_MAILTO;
01412 else
01413 if ( targetOpensNewWindow( m_part, mev.target.string() ) )
01414 linkCursor = LINK_NEWWINDOW;
01415 break;
01416 case CURSOR_PROGRESS:
01417 c = QCursor(Qt::BusyCursor);
01418 break;
01419 case CURSOR_MOVE:
01420 case CURSOR_ALL_SCROLL:
01421 c = QCursor(Qt::SizeAllCursor);
01422 break;
01423 case CURSOR_E_RESIZE:
01424 case CURSOR_W_RESIZE:
01425 case CURSOR_EW_RESIZE:
01426 c = QCursor(Qt::SizeHorCursor);
01427 break;
01428 case CURSOR_N_RESIZE:
01429 case CURSOR_S_RESIZE:
01430 case CURSOR_NS_RESIZE:
01431 c = QCursor(Qt::SizeVerCursor);
01432 break;
01433 case CURSOR_NE_RESIZE:
01434 case CURSOR_SW_RESIZE:
01435 case CURSOR_NESW_RESIZE:
01436 c = QCursor(Qt::SizeBDiagCursor);
01437 break;
01438 case CURSOR_NW_RESIZE:
01439 case CURSOR_SE_RESIZE:
01440 case CURSOR_NWSE_RESIZE:
01441 c = QCursor(Qt::SizeFDiagCursor);
01442 break;
01443 case CURSOR_TEXT:
01444 c = QCursor(Qt::IBeamCursor);
01445 break;
01446 case CURSOR_WAIT:
01447 c = QCursor(Qt::WaitCursor);
01448 break;
01449 case CURSOR_HELP:
01450 c = QCursor(Qt::WhatsThisCursor);
01451 break;
01452 case CURSOR_DEFAULT:
01453 break;
01454 case CURSOR_NONE:
01455 case CURSOR_NOT_ALLOWED:
01456 c = QCursor(Qt::ForbiddenCursor);
01457 break;
01458 case CURSOR_ROW_RESIZE:
01459 c = QCursor(Qt::SplitVCursor);
01460 break;
01461 case CURSOR_COL_RESIZE:
01462 c = QCursor(Qt::SplitHCursor);
01463 break;
01464 case CURSOR_VERTICAL_TEXT:
01465 case CURSOR_CONTEXT_MENU:
01466 case CURSOR_NO_DROP:
01467 case CURSOR_CELL:
01468 case CURSOR_COPY:
01469 case CURSOR_ALIAS:
01470 c = QCursor(Qt::ArrowCursor);
01471 break;
01472 }
01473
01474 if (!setCursor && style && style->cursor() != CURSOR_AUTO)
01475 setCursor = true;
01476
01477 QWidget* vp = viewport();
01478 for (KHTMLPart* p = m_part; p; p = p->parentPart())
01479 if (!p->parentPart())
01480 vp = p->view()->viewport();
01481 if ( setCursor && vp->cursor().handle() != c.handle() ) {
01482 if( c.shape() == Qt::ArrowCursor) {
01483 for (KHTMLPart* p = m_part; p; p = p->parentPart())
01484 p->view()->viewport()->unsetCursor();
01485 }
01486 else {
01487 vp->setCursor( c );
01488 }
01489 }
01490
01491 if ( linkCursor!=LINK_NORMAL && isVisible() && hasFocus() ) {
01492 #ifdef Q_WS_X11
01493
01494 if( !d->cursorIconWidget ) {
01495 #ifdef Q_WS_X11
01496 d->cursorIconWidget = new QLabel( 0, Qt::X11BypassWindowManagerHint );
01497 XSetWindowAttributes attr;
01498 attr.save_under = True;
01499 XChangeWindowAttributes( QX11Info::display(), d->cursorIconWidget->winId(), CWSaveUnder, &attr );
01500 #else
01501 d->cursorIconWidget = new QLabel( NULL, NULL );
01502
01503 #endif
01504 }
01505
01506
01507 if (linkCursor != d->cursorIconType) {
01508 d->cursorIconType = linkCursor;
01509 QString cursorIcon;
01510 switch (linkCursor)
01511 {
01512 case LINK_MAILTO: cursorIcon = "mail-message-new"; break;
01513 case LINK_NEWWINDOW: cursorIcon = "window-new"; break;
01514 default: cursorIcon = "dialog-error"; break;
01515 }
01516
01517 QPixmap icon_pixmap = KHTMLGlobal::iconLoader()->loadIcon( cursorIcon, KIconLoader::Small, 0, KIconLoader::DefaultState, QStringList(), 0, true );
01518
01519 d->cursorIconWidget->resize( icon_pixmap.width(), icon_pixmap.height());
01520 d->cursorIconWidget->setMask( icon_pixmap.createMaskFromColor(Qt::transparent));
01521 d->cursorIconWidget->setPixmap( icon_pixmap);
01522 d->cursorIconWidget->update();
01523 }
01524
01525 QPoint c_pos = QCursor::pos();
01526 d->cursorIconWidget->move( c_pos.x() + 15, c_pos.y() + 15 );
01527 #ifdef Q_WS_X11
01528 XRaiseWindow( QX11Info::display(), d->cursorIconWidget->winId());
01529 QApplication::flush();
01530 #elif defined(Q_WS_WIN)
01531 SetWindowPos( d->cursorIconWidget->winId(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
01532 #else
01533
01534 #endif
01535 d->cursorIconWidget->show();
01536 #endif
01537 }
01538 else if ( d->cursorIconWidget )
01539 d->cursorIconWidget->hide();
01540
01541 if (r && r->isWidget()) {
01542 _mouse->ignore();
01543 }
01544
01545 if (!swallowEvent) {
01546 khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
01547 QApplication::sendEvent( m_part, &event );
01548 }
01549 }
01550
01551 void KHTMLView::mouseReleaseEvent( QMouseEvent * _mouse )
01552 {
01553 bool swallowEvent = false;
01554
01555 int xm = _mouse->x();
01556 int ym = _mouse->y();
01557 revertTransforms(xm, ym);
01558
01559 DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MouseRelease );
01560
01561 if ( m_part->xmlDocImpl() )
01562 {
01563 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
01564
01565 DOM::NodeImpl* target = mev.innerNode.handle();
01566 DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode();
01567
01568
01569 if (d->m_mouseEventsTarget && fn && fn->renderer() && fn->renderer()->isWidget())
01570 target = fn;
01571
01572 swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,target,mev.innerNonSharedNode.handle(),true,
01573 d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease);
01574
01575
01576 if (d->m_mouseEventsTarget)
01577 d->m_mouseEventsTarget = 0;
01578
01579 if (d->clickCount > 0 &&
01580 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance()) {
01581 QMouseEvent me(d->isDoubleClick ? QEvent::MouseButtonDblClick : QEvent::MouseButtonRelease,
01582 _mouse->pos(), _mouse->button(), _mouse->buttons(), _mouse->modifiers());
01583 dispatchMouseEvent(EventImpl::CLICK_EVENT, mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01584 d->clickCount, &me, true, DOM::NodeImpl::MouseRelease);
01585 }
01586
01587 khtml::RenderObject* r = target ? target->renderer() : 0;
01588 if (r && r->isWidget())
01589 _mouse->ignore();
01590 }
01591
01592 if (!swallowEvent) {
01593 khtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
01594 QApplication::sendEvent( m_part, &event );
01595 }
01596 }
01597
01598
01599 bool KHTMLView::dispatchKeyEvent( QKeyEvent *_ke )
01600 {
01601 if (!m_part->xmlDocImpl())
01602 return false;
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623 if( _ke == d->postponed_autorepeat )
01624 {
01625 return false;
01626 }
01627
01628 if( _ke->type() == QEvent::KeyPress )
01629 {
01630 if( !_ke->isAutoRepeat())
01631 {
01632 bool ret = dispatchKeyEventHelper( _ke, false );
01633
01634 if( !ret && dispatchKeyEventHelper( _ke, true ))
01635 ret = true;
01636 return ret;
01637 }
01638 else
01639 {
01640 bool ret = dispatchKeyEventHelper( _ke, true );
01641 if( !ret && d->postponed_autorepeat )
01642 keyPressEvent( d->postponed_autorepeat );
01643 delete d->postponed_autorepeat;
01644 d->postponed_autorepeat = NULL;
01645 return ret;
01646 }
01647 }
01648 else
01649 {
01650
01651
01652 if ( d->postponed_autorepeat ) {
01653 delete d->postponed_autorepeat;
01654 d->postponed_autorepeat = 0;
01655 }
01656
01657 if( !_ke->isAutoRepeat()) {
01658 return dispatchKeyEventHelper( _ke, false );
01659 }
01660 else
01661 {
01662 d->postponed_autorepeat = new QKeyEvent( _ke->type(), _ke->key(), _ke->modifiers(),
01663 _ke->text(), _ke->isAutoRepeat(), _ke->count());
01664 if( _ke->isAccepted())
01665 d->postponed_autorepeat->accept();
01666 else
01667 d->postponed_autorepeat->ignore();
01668 return true;
01669 }
01670 }
01671 }
01672
01673
01674 bool KHTMLView::dispatchKeyEventHelper( QKeyEvent *_ke, bool keypress )
01675 {
01676 DOM::NodeImpl* keyNode = m_part->xmlDocImpl()->focusNode();
01677 if (keyNode) {
01678 return keyNode->dispatchKeyEvent(_ke, keypress);
01679 } else {
01680 return m_part->xmlDocImpl()->dispatchKeyEvent(_ke, keypress);
01681 }
01682 }
01683
01684 void KHTMLView::keyPressEvent( QKeyEvent *_ke )
01685 {
01686 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01687 if(d->typeAheadActivated)
01688 {
01689
01690 if(_ke->key() == Qt::Key_Backspace)
01691 {
01692 d->findString = d->findString.left(d->findString.length() - 1);
01693
01694 if(!d->findString.isEmpty())
01695 {
01696 findAhead(false);
01697 }
01698 else
01699 {
01700 findTimeout();
01701 }
01702
01703 d->timer.setSingleShot(true);
01704 d->timer.start(3000);
01705 _ke->accept();
01706 return;
01707 }
01708 else if(_ke->key() == Qt::Key_Escape)
01709 {
01710 findTimeout();
01711
01712 _ke->accept();
01713 return;
01714 }
01715 else if(_ke->key() == Qt::Key_Space || !_ke->text().trimmed().isEmpty())
01716 {
01717 d->findString += _ke->text();
01718
01719 findAhead(true);
01720
01721 d->timer.setSingleShot(true);
01722 d->timer.start(3000);
01723 _ke->accept();
01724 return;
01725 }
01726 }
01727 #endif // KHTML_NO_TYPE_AHEAD_FIND
01728
01729
01730 if (d->accessKeysEnabled && _ke->key() == Qt::Key_Control && !(_ke->modifiers() & ~Qt::ControlModifier) && !d->accessKeysActivated)
01731 {
01732 d->accessKeysPreActivate=true;
01733 _ke->accept();
01734 return;
01735 }
01736
01737 if (_ke->key() == Qt::Key_Shift && !(_ke->modifiers() & ~Qt::ShiftModifier))
01738 d->scrollSuspendPreActivate=true;
01739
01740
01741
01742
01743 if (d->accessKeysEnabled && d->accessKeysActivated)
01744 {
01745 int state = ( _ke->modifiers() & ( Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier ));
01746 if ( state==0 || state==Qt::ShiftModifier) {
01747 if (_ke->key() != Qt::Key_Shift) accessKeysTimeout();
01748 handleAccessKey( _ke );
01749 _ke->accept();
01750 return;
01751 }
01752 accessKeysTimeout();
01753 }
01754
01755 if ( dispatchKeyEvent( _ke )) {
01756
01757 _ke->accept();
01758 return;
01759 }
01760
01761 int offs = (viewport()->height() < 30) ? viewport()->height() : 30;
01762 if (_ke->modifiers() & Qt::ShiftModifier)
01763 switch(_ke->key())
01764 {
01765 case Qt::Key_Space:
01766 verticalScrollBar()->setValue( verticalScrollBar()->value() -viewport()->height() + offs );
01767 if(d->scrollSuspended)
01768 d->newScrollTimer(this, 0);
01769 break;
01770
01771 case Qt::Key_Down:
01772 case Qt::Key_J:
01773 d->adjustScroller(this, KHTMLViewPrivate::ScrollDown, KHTMLViewPrivate::ScrollUp);
01774 break;
01775
01776 case Qt::Key_Up:
01777 case Qt::Key_K:
01778 d->adjustScroller(this, KHTMLViewPrivate::ScrollUp, KHTMLViewPrivate::ScrollDown);
01779 break;
01780
01781 case Qt::Key_Left:
01782 case Qt::Key_H:
01783 d->adjustScroller(this, KHTMLViewPrivate::ScrollLeft, KHTMLViewPrivate::ScrollRight);
01784 break;
01785
01786 case Qt::Key_Right:
01787 case Qt::Key_L:
01788 d->adjustScroller(this, KHTMLViewPrivate::ScrollRight, KHTMLViewPrivate::ScrollLeft);
01789 break;
01790 }
01791 else
01792 switch ( _ke->key() )
01793 {
01794 case Qt::Key_Down:
01795 case Qt::Key_J:
01796 if (!d->scrollTimerId || d->scrollSuspended)
01797 verticalScrollBar()->setValue( verticalScrollBar()->value()+10 );
01798 if (d->scrollTimerId)
01799 d->newScrollTimer(this, 0);
01800 break;
01801
01802 case Qt::Key_Space:
01803 case Qt::Key_PageDown:
01804 d->shouldSmoothScroll = true;
01805 verticalScrollBar()->setValue( verticalScrollBar()->value() +viewport()->height() - offs );
01806 if(d->scrollSuspended)
01807 d->newScrollTimer(this, 0);
01808 break;
01809
01810 case Qt::Key_Up:
01811 case Qt::Key_K:
01812 if (!d->scrollTimerId || d->scrollSuspended)
01813 verticalScrollBar()->setValue( verticalScrollBar()->value()-10 );
01814 if (d->scrollTimerId)
01815 d->newScrollTimer(this, 0);
01816 break;
01817
01818 case Qt::Key_PageUp:
01819 d->shouldSmoothScroll = true;
01820 verticalScrollBar()->setValue( verticalScrollBar()->value() -viewport()->height() + offs );
01821 if(d->scrollSuspended)
01822 d->newScrollTimer(this, 0);
01823 break;
01824 case Qt::Key_Right:
01825 case Qt::Key_L:
01826 if (!d->scrollTimerId || d->scrollSuspended)
01827 horizontalScrollBar()->setValue( horizontalScrollBar()->value()+10 );
01828 if (d->scrollTimerId)
01829 d->newScrollTimer(this, 0);
01830 break;
01831
01832 case Qt::Key_Left:
01833 case Qt::Key_H:
01834 if (!d->scrollTimerId || d->scrollSuspended)
01835 horizontalScrollBar()->setValue( horizontalScrollBar()->value()-10 );
01836 if (d->scrollTimerId)
01837 d->newScrollTimer(this, 0);
01838 break;
01839 case Qt::Key_Enter:
01840 case Qt::Key_Return:
01841
01842
01843 if (m_part->xmlDocImpl()) {
01844 NodeImpl *n = m_part->xmlDocImpl()->focusNode();
01845 if (n)
01846 n->setActive();
01847 }
01848 break;
01849 case Qt::Key_Home:
01850 verticalScrollBar()->setValue( 0 );
01851 horizontalScrollBar()->setValue( 0 );
01852 if(d->scrollSuspended)
01853 d->newScrollTimer(this, 0);
01854 break;
01855 case Qt::Key_End:
01856 verticalScrollBar()->setValue( contentsHeight() - visibleHeight() );
01857 if(d->scrollSuspended)
01858 d->newScrollTimer(this, 0);
01859 break;
01860 case Qt::Key_Shift:
01861
01862 _ke->ignore();
01863 return;
01864 default:
01865 if (d->scrollTimerId)
01866 d->newScrollTimer(this, 0);
01867 _ke->ignore();
01868 return;
01869 }
01870
01871 _ke->accept();
01872 }
01873
01874 void KHTMLView::findTimeout()
01875 {
01876 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01877 d->typeAheadActivated = false;
01878 d->findString = "";
01879 m_part->setStatusBarText(i18n("Find stopped."), KHTMLPart::BarDefaultText);
01880 m_part->enableFindAheadActions( true );
01881 #endif // KHTML_NO_TYPE_AHEAD_FIND
01882 }
01883
01884 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01885 void KHTMLView::startFindAhead( bool linksOnly )
01886 {
01887 if( linksOnly )
01888 {
01889 d->findLinksOnly = true;
01890 m_part->setStatusBarText(i18n("Starting -- find links as you type"),
01891 KHTMLPart::BarDefaultText);
01892 }
01893 else
01894 {
01895 d->findLinksOnly = false;
01896 m_part->setStatusBarText(i18n("Starting -- find text as you type"),
01897 KHTMLPart::BarDefaultText);
01898 }
01899
01900 m_part->findTextBegin();
01901 d->typeAheadActivated = true;
01902
01903 m_part->enableFindAheadActions( false );
01904 d->timer.setSingleShot(true);
01905 d->timer.start(3000);
01906 }
01907
01908 void KHTMLView::findAhead(bool increase)
01909 {
01910 QString status;
01911 QString text = d->findString.toLower();
01912
01913 if(d->findLinksOnly)
01914 {
01915 m_part->findText(d->findString, KHTMLPart::FindNoPopups |
01916 KHTMLPart::FindLinksOnly, this);
01917 if(m_part->findTextNext())
01918 {
01919 status = i18n("Link found: \"%1\".", Qt::escape(text));
01920 }
01921 else
01922 {
01923 if(increase) KNotification::beep();
01924 status = i18n("Link not found: \"%1\".", Qt::escape(text));
01925 }
01926 }
01927 else
01928 {
01929 m_part->findText(d->findString, KHTMLPart::FindNoPopups, this);
01930 if(m_part->findTextNext())
01931 {
01932 status = i18n("Text found: \"%1\".", Qt::escape(text));
01933 }
01934 else
01935 {
01936 if(increase) KNotification::beep();
01937 status = i18n("Text not found: \"%1\".", Qt::escape(text));
01938 }
01939 }
01940
01941
01942 m_part->setStatusBarText(Qt::escape(status), KHTMLPart::BarDefaultText);
01943 }
01944
01945 void KHTMLView::updateFindAheadTimeout()
01946 {
01947 if( d->typeAheadActivated ) {
01948 d->timer.setSingleShot( true );
01949 d->timer.start( 3000 );
01950 }
01951 }
01952
01953 #endif // KHTML_NO_TYPE_AHEAD_FIND
01954
01955 void KHTMLView::keyReleaseEvent(QKeyEvent *_ke)
01956 {
01957 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01958 if(d->typeAheadActivated) {
01959 _ke->accept();
01960 return;
01961 }
01962 #endif
01963
01964 if( d->scrollSuspendPreActivate && _ke->key() != Qt::Key_Shift )
01965 d->scrollSuspendPreActivate = false;
01966 if( _ke->key() == Qt::Key_Shift && d->scrollSuspendPreActivate && !(_ke->modifiers() & Qt::ShiftModifier))
01967 if (d->scrollTimerId) {
01968 d->scrollSuspended = !d->scrollSuspended;
01969 if (d->scrollSuspended)
01970 d->stopScrolling();
01971 }
01972
01973 if (d->accessKeysEnabled)
01974 {
01975 if (d->accessKeysPreActivate && _ke->key() != Qt::Key_Control)
01976 d->accessKeysPreActivate=false;
01977 if (d->accessKeysPreActivate && !(_ke->modifiers() & Qt::ControlModifier))
01978 {
01979 displayAccessKeys();
01980 m_part->setStatusBarText(i18n("Access Keys activated"),KHTMLPart::BarOverrideText);
01981 d->accessKeysActivated = true;
01982 d->accessKeysPreActivate = false;
01983 _ke->accept();
01984 return;
01985 }
01986 else if (d->accessKeysActivated)
01987 {
01988 accessKeysTimeout();
01989 _ke->accept();
01990 return;
01991 }
01992 }
01993
01994
01995 if ( dispatchKeyEvent( _ke ) )
01996 {
01997 _ke->accept();
01998 return;
01999 }
02000
02001 QScrollArea::keyReleaseEvent(_ke);
02002 }
02003
02004 bool KHTMLView::focusNextPrevChild( bool next )
02005 {
02006
02007 if (m_part->xmlDocImpl() && focusNextPrevNode(next))
02008 {
02009 if (m_part->xmlDocImpl()->focusNode())
02010 kDebug() << "focusNode.name: "
02011 << m_part->xmlDocImpl()->focusNode()->nodeName().string() << endl;
02012 return true;
02013 }
02014
02015
02016 d->pseudoFocusNode = KHTMLViewPrivate::PFNone;
02017 if (m_part->parentPart() && m_part->parentPart()->view())
02018 return m_part->parentPart()->view()->focusNextPrevChild(next);
02019
02020 return QWidget::focusNextPrevChild(next);
02021 }
02022
02023 void KHTMLView::doAutoScroll()
02024 {
02025 QPoint pos = QCursor::pos();
02026 QPoint off;
02027 KHTMLView* v = m_kwp->isRedirected() ? m_kwp->rootViewPos(off) : this;
02028 pos = v->viewport()->mapFromGlobal( pos );
02029 pos -= off;
02030 int xm, ym;
02031 viewportToContents(pos.x(), pos.y(), xm, ym);
02032
02033 pos = QPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y());
02034 if ( (pos.y() < 0) || (pos.y() > visibleHeight()) ||
02035 (pos.x() < 0) || (pos.x() > visibleWidth()) )
02036 {
02037 ensureVisible( xm, ym, 0, 5 );
02038
02039 #ifndef KHTML_NO_SELECTION
02040
02041 DOM::Node innerNode;
02042 if (m_part->isExtendingSelection()) {
02043 RenderObject::NodeInfo renderInfo(true, false);
02044 m_part->xmlDocImpl()->renderer()->layer()
02045 ->nodeAtPoint(renderInfo, xm, ym);
02046 innerNode = renderInfo.innerNode();
02047 }
02048
02049 if (innerNode.handle() && innerNode.handle()->renderer()
02050 && innerNode.handle()->renderer()->shouldSelect()) {
02051 m_part->extendSelectionTo(xm, ym, innerNode);
02052 }
02053 #endif // KHTML_NO_SELECTION
02054 }
02055 }
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074 static void handleWidget(QWidget* w, KHTMLView* view, bool recurse=true)
02075 {
02076 if (w->isWindow())
02077 return;
02078
02079 if (!qobject_cast<QFrame*>(w))
02080 w->setAttribute( Qt::WA_NoSystemBackground );
02081
02082 w->setAttribute(Qt::WA_WState_InPaintEvent);
02083 w->setAttribute(Qt::WA_OpaquePaintEvent);
02084 w->installEventFilter(view);
02085
02086 if (!recurse)
02087 return;
02088 if (qobject_cast<KHTMLView*>(w)) {
02089 handleWidget(static_cast<KHTMLView*>(w)->widget(), view, false);
02090 handleWidget(static_cast<KHTMLView*>(w)->horizontalScrollBar(), view, false);
02091 handleWidget(static_cast<KHTMLView*>(w)->verticalScrollBar(), view, false);
02092 return;
02093 }
02094
02095 QObjectList children = w->children();
02096 foreach (QObject* object, children) {
02097 QWidget *widget = qobject_cast<QWidget*>(object);
02098 if (widget)
02099 handleWidget(widget, view);
02100 }
02101 }
02102
02103 class KHTMLBackingStoreHackWidget : public QWidget
02104 {
02105 public:
02106 void publicEvent(QEvent *e)
02107 {
02108 QWidget::event(e);
02109 }
02110 };
02111
02112 bool KHTMLView::viewportEvent ( QEvent * e )
02113 {
02114 switch (e->type()) {
02115
02116
02117 case QEvent::MouseButtonPress:
02118 case QEvent::MouseButtonRelease:
02119 case QEvent::MouseButtonDblClick:
02120 case QEvent::MouseMove:
02121 #ifndef QT_NO_WHEELEVENT
02122 case QEvent::Wheel:
02123 #endif
02124 case QEvent::ContextMenu:
02125 case QEvent::DragEnter:
02126 case QEvent::DragMove:
02127 case QEvent::DragLeave:
02128 case QEvent::Drop:
02129 return false;
02130 case QEvent::Paint: {
02131 QRect r = static_cast<QPaintEvent*>(e)->rect();
02132 r.setX(r.x() +contentsX());
02133 r.setY(r.y() +contentsY());
02134 QPaintEvent pe(r);
02135 paintEvent(&pe);
02136 return true;
02137 }
02138 default:
02139 break;
02140 }
02141 return QScrollArea::viewportEvent(e);
02142 }
02143
02144 static void setInPaintEventFlag(QWidget* w, bool b = true, bool recurse=true)
02145 {
02146 w->setAttribute(Qt::WA_WState_InPaintEvent, b);
02147
02148 if (!recurse)
02149 return;
02150 if (qobject_cast<KHTMLView*>(w)) {
02151 setInPaintEventFlag(static_cast<KHTMLView*>(w)->widget(), b, false);
02152 setInPaintEventFlag(static_cast<KHTMLView*>(w)->horizontalScrollBar(), b, false);
02153 setInPaintEventFlag(static_cast<KHTMLView*>(w)->verticalScrollBar(), b, false);
02154 return;
02155 }
02156
02157 foreach(QObject* cw, w->children()) {
02158 if (cw->isWidgetType() && ! static_cast<QWidget*>(cw)->isWindow()
02159 && !(static_cast<QWidget*>(cw)->windowModality() & Qt::ApplicationModal)) {
02160 setInPaintEventFlag(static_cast<QWidget*>(cw), b);
02161 }
02162 }
02163 }
02164
02165 bool KHTMLView::eventFilter(QObject *o, QEvent *e)
02166 {
02167 if ( e->type() == QEvent::ShortcutOverride ) {
02168 QKeyEvent* ke = (QKeyEvent*) e;
02169 if (m_part->isEditable() || m_part->isCaretMode()
02170 || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()
02171 && m_part->xmlDocImpl()->focusNode()->isContentEditable())) {
02172 if ( (ke->modifiers() & Qt::ControlModifier) || (ke->modifiers() & Qt::ShiftModifier) ) {
02173 switch ( ke->key() ) {
02174 case Qt::Key_Left:
02175 case Qt::Key_Right:
02176 case Qt::Key_Up:
02177 case Qt::Key_Down:
02178 case Qt::Key_Home:
02179 case Qt::Key_End:
02180 ke->accept();
02181 return true;
02182 default:
02183 break;
02184 }
02185 }
02186 }
02187 }
02188
02189 if ( e->type() == QEvent::Leave ) {
02190 if ( d->cursorIconWidget )
02191 d->cursorIconWidget->hide();
02192 m_part->resetHoverText();
02193 }
02194
02195 QWidget *view = widget();
02196 if (o == view) {
02197 if (widgetEvent(e))
02198 return true;
02199 else if (e->type() == QEvent::Resize) {
02200 updateScrollBars();
02201 return false;
02202 }
02203 } else if (o->isWidgetType()) {
02204 QWidget *v = static_cast<QWidget *>(o);
02205 QWidget *c = v;
02206 while (v && v != view) {
02207 c = v;
02208 v = v->parentWidget();
02209 }
02210 KHTMLWidget* k = dynamic_cast<KHTMLWidget*>(c);
02211 if (v && k && k->m_kwp->isRedirected()) {
02212 bool block = false;
02213 bool isUpdate = false;
02214 QWidget *w = static_cast<QWidget *>(o);
02215 switch(e->type()) {
02216 case QEvent::UpdateRequest: {
02217
02218 static_cast<KHTMLBackingStoreHackWidget *>(w)->publicEvent(e);
02219 block = true;
02220 break;
02221 }
02222 case QEvent::UpdateLater:
02223 isUpdate = true;
02224
02225 case QEvent::Paint:
02226 if (!allowWidgetPaintEvents) {
02227
02228
02229 block = true;
02230 int x = 0, y = 0;
02231 QWidget *v = w;
02232 while (v && v->parentWidget() != view) {
02233 x += v->x();
02234 y += v->y();
02235 v = v->parentWidget();
02236 }
02237
02238 QPoint ap = k->m_kwp->absolutePos();
02239 x += ap.x();
02240 y += ap.y();
02241
02242 QRect pr = isUpdate ? static_cast<QUpdateLaterEvent*>(e)->region().boundingRect() : static_cast<QPaintEvent*>(e)->rect();
02243 bool asap = !d->contentsMoving && qobject_cast<QAbstractScrollArea*>(c);
02244
02245 if (isUpdate) {
02246 setInPaintEventFlag(w, false);
02247 if (asap)
02248 w->repaint(static_cast<QUpdateLaterEvent*>(e)->region());
02249 else
02250 w->update(static_cast<QUpdateLaterEvent*>(e)->region());
02251 setInPaintEventFlag(w);
02252 }
02253
02254
02255 if ( asap && !isUpdate && !d->painting && m_part->xmlDocImpl() && m_part->xmlDocImpl()->renderer() &&
02256 !static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer())->needsLayout() ) {
02257 repaintContents(x + pr.x(), y + pr.y(),
02258 pr.width(), pr.height()+1);
02259
02260 } else if (!d->painting) {
02261 scheduleRepaint(x + pr.x(), y + pr.y(),
02262 pr.width(), pr.height()+1, asap);
02263 }
02264 }
02265 break;
02266 case QEvent::MouseMove:
02267 case QEvent::MouseButtonPress:
02268 case QEvent::MouseButtonRelease:
02269 case QEvent::MouseButtonDblClick: {
02270
02271 if (0 && w->parentWidget() == view && !qobject_cast<QScrollBar*>(w) && !::qobject_cast<QScrollBar *>(w)) {
02272 QMouseEvent *me = static_cast<QMouseEvent *>(e);
02273 QPoint pt = w->mapTo( view, me->pos());
02274 QMouseEvent me2(me->type(), pt, me->button(), me->buttons(), me->modifiers());
02275
02276 if (e->type() == QEvent::MouseMove)
02277 mouseMoveEvent(&me2);
02278 else if(e->type() == QEvent::MouseButtonPress)
02279 mousePressEvent(&me2);
02280 else if(e->type() == QEvent::MouseButtonRelease)
02281 mouseReleaseEvent(&me2);
02282 else
02283 mouseDoubleClickEvent(&me2);
02284 block = true;
02285 }
02286 break;
02287 }
02288 case QEvent::KeyPress:
02289 case QEvent::KeyRelease:
02290 if (w->parentWidget() == view && !qobject_cast<QScrollBar*>(w)) {
02291 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
02292 if (e->type() == QEvent::KeyPress)
02293 keyPressEvent(ke);
02294 else
02295 keyReleaseEvent(ke);
02296 block = true;
02297 }
02298
02299 if (qobject_cast<KUrlRequester*>(w->parentWidget()) &&
02300 e->type() == QEvent::KeyPress) {
02301
02302
02303
02304
02305 e->ignore();
02306 block = true;
02307 }
02308
02309 break;
02310 case QEvent::FocusIn:
02311 case QEvent::FocusOut:
02312 block = true;
02313 break;
02314 default:
02315 break;
02316 }
02317 if (block) {
02318
02319 return true;
02320 }
02321 }
02322 }
02323
02324
02325 return QScrollArea::eventFilter(o, e);
02326 }
02327
02328 bool KHTMLView::widgetEvent(QEvent* e)
02329 {
02330 switch (e->type()) {
02331 case QEvent::MouseButtonPress:
02332 case QEvent::MouseButtonRelease:
02333 case QEvent::MouseButtonDblClick:
02334 case QEvent::MouseMove:
02335 case QEvent::Paint:
02336 #ifndef QT_NO_WHEELEVENT
02337 case QEvent::Wheel:
02338 #endif
02339 case QEvent::ContextMenu:
02340 case QEvent::DragEnter:
02341 case QEvent::DragMove:
02342 case QEvent::DragLeave:
02343 case QEvent::Drop:
02344 return QFrame::event(e);
02345 case QEvent::ChildPolished: {
02346
02347
02348 QObject *c = static_cast<QChildEvent *>(e)->child();
02349 if (c->isWidgetType()) {
02350 QWidget *w = static_cast<QWidget *>(c);
02351
02352 if (!(w->windowFlags() & Qt::Window) && !(w->windowModality() & Qt::ApplicationModal)) {
02353 KHTMLWidget* k = dynamic_cast<KHTMLWidget*>(w);
02354 if (k && k->m_kwp->isRedirected()) {
02355 w->unsetCursor();
02356 handleWidget(w, this);
02357 }
02358 }
02359 }
02360 break;
02361 }
02362 case QEvent::Move: {
02363 if (static_cast<QMoveEvent*>(e)->pos() != QPoint(0,0)) {
02364 widget()->move(0,0);
02365 updateScrollBars();
02366 return true;
02367 }
02368 break;
02369 }
02370 default:
02371 break;
02372 }
02373 return false;
02374 }
02375
02376 DOM::NodeImpl *KHTMLView::nodeUnderMouse() const
02377 {
02378 return d->underMouse;
02379 }
02380
02381 DOM::NodeImpl *KHTMLView::nonSharedNodeUnderMouse() const
02382 {
02383 return d->underMouseNonShared;
02384 }
02385
02386 bool KHTMLView::scrollTo(const QRect &bounds)
02387 {
02388 d->scrollingSelf = true;
02389
02390 int x, y, xe, ye;
02391 x = bounds.left();
02392 y = bounds.top();
02393 xe = bounds.right();
02394 ye = bounds.bottom();
02395
02396
02397
02398 int deltax;
02399 int deltay;
02400
02401 int curHeight = visibleHeight();
02402 int curWidth = visibleWidth();
02403
02404 if (ye-y>curHeight-d->borderY)
02405 ye = y + curHeight - d->borderY;
02406
02407 if (xe-x>curWidth-d->borderX)
02408 xe = x + curWidth - d->borderX;
02409
02410
02411 if (x < contentsX() + d->borderX )
02412 deltax = x - contentsX() - d->borderX;
02413
02414 else if (xe + d->borderX > contentsX() + curWidth)
02415 deltax = xe + d->borderX - ( contentsX() + curWidth );
02416 else
02417 deltax = 0;
02418
02419
02420 if (y < contentsY() + d->borderY)
02421 deltay = y - contentsY() - d->borderY;
02422
02423 else if (ye + d->borderY > contentsY() + curHeight)
02424 deltay = ye + d->borderY - ( contentsY() + curHeight );
02425 else
02426 deltay = 0;
02427
02428 int maxx = curWidth-d->borderX;
02429 int maxy = curHeight-d->borderY;
02430
02431 int scrollX, scrollY;
02432
02433 scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax>-maxx ? deltax : -maxx);
02434 scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay>-maxy ? deltay : -maxy);
02435
02436 if (contentsX() + scrollX < 0)
02437 scrollX = -contentsX();
02438 else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
02439 scrollX = contentsWidth() - visibleWidth() - contentsX();
02440
02441 if (contentsY() + scrollY < 0)
02442 scrollY = -contentsY();
02443 else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
02444 scrollY = contentsHeight() - visibleHeight() - contentsY();
02445
02446 horizontalScrollBar()->setValue( horizontalScrollBar()->value()+scrollX );
02447 verticalScrollBar()->setValue( verticalScrollBar()->value()+scrollY );
02448
02449 d->scrollingSelf = false;
02450
02451 if ( (abs(deltax)<=maxx) && (abs(deltay)<=maxy) )
02452 return true;
02453 else return false;
02454
02455 }
02456
02457 bool KHTMLView::focusNextPrevNode(bool next)
02458 {
02459
02460
02461
02462
02463
02464
02465
02466 DocumentImpl *doc = m_part->xmlDocImpl();
02467 NodeImpl *oldFocusNode = doc->focusNode();
02468
02469
02470
02471
02472
02473 if (oldFocusNode) {
02474 if ((oldFocusNode->renderer() && !oldFocusNode->renderer()->parent())
02475 || !oldFocusNode->isTabFocusable()) {
02476 doc->quietResetFocus();
02477 return true;
02478 }
02479 }
02480
02481 #if 1
02482
02483
02484
02485 if (d->scrollBarMoved)
02486 {
02487 NodeImpl *toFocus;
02488 if (next)
02489 toFocus = doc->nextFocusNode(oldFocusNode);
02490 else
02491 toFocus = doc->previousFocusNode(oldFocusNode);
02492
02493 if (!toFocus && oldFocusNode) {
02494 if (next)
02495 toFocus = doc->nextFocusNode(NULL);
02496 else
02497 toFocus = doc->previousFocusNode(NULL);
02498 }
02499
02500 while (toFocus && toFocus != oldFocusNode)
02501 {
02502
02503 QRect focusNodeRect = toFocus->getRect();
02504 if ((focusNodeRect.left() > contentsX()) && (focusNodeRect.right() < contentsX() + visibleWidth()) &&
02505 (focusNodeRect.top() > contentsY()) && (focusNodeRect.bottom() < contentsY() + visibleHeight())) {
02506 {
02507 QRect r = toFocus->getRect();
02508 ensureVisible( r.right(), r.bottom());
02509 ensureVisible( r.left(), r.top());
02510 d->scrollBarMoved = false;
02511 d->tabMovePending = false;
02512 d->lastTabbingDirection = next;
02513 d->pseudoFocusNode = KHTMLViewPrivate::PFNone;
02514 m_part->xmlDocImpl()->setFocusNode(toFocus);
02515 Node guard(toFocus);
02516 if (!toFocus->hasOneRef() )
02517 {
02518 emit m_part->nodeActivated(Node(toFocus));
02519 }
02520 return true;
02521 }
02522 }
02523 if (next)
02524 toFocus = doc->nextFocusNode(toFocus);
02525 else
02526 toFocus = doc->previousFocusNode(toFocus);
02527
02528 if (!toFocus && oldFocusNode)
02529 {
02530 if (next)
02531 {
02532 toFocus = doc->nextFocusNode(NULL);
02533 }
02534 else
02535 {
02536 toFocus = doc->previousFocusNode(NULL);
02537 }
02538 }
02539 }
02540
02541 d->scrollBarMoved = false;
02542 }
02543 #endif
02544
02545 if (!oldFocusNode && d->pseudoFocusNode == KHTMLViewPrivate::PFNone)
02546 {
02547 ensureVisible(contentsX(), next?0:contentsHeight());
02548 d->scrollBarMoved = false;
02549 d->pseudoFocusNode = next?KHTMLViewPrivate::PFTop:KHTMLViewPrivate::PFBottom;
02550 return true;
02551 }
02552
02553 NodeImpl *newFocusNode = NULL;
02554
02555 if (d->tabMovePending && next != d->lastTabbingDirection)
02556 {
02557
02558 newFocusNode = oldFocusNode;
02559 }
02560 else if (next)
02561 {
02562 if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFTop )
02563 newFocusNode = doc->nextFocusNode(oldFocusNode);
02564 }
02565 else
02566 {
02567 if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFBottom )
02568 newFocusNode = doc->previousFocusNode(oldFocusNode);
02569 }
02570
02571 bool targetVisible = false;
02572 if (!newFocusNode)
02573 {
02574 if ( next )
02575 {
02576 targetVisible = scrollTo(QRect(contentsX()+visibleWidth()/2,contentsHeight()-d->borderY,0,0));
02577 }
02578 else
02579 {
02580 targetVisible = scrollTo(QRect(contentsX()+visibleWidth()/2,d->borderY,0,0));
02581 }
02582 }
02583 else
02584 {
02585
02586 if (!m_part->isCaretMode() && newFocusNode->isContentEditable()) {
02587 kDebug(6200) << "show caret! fn: " << newFocusNode->nodeName().string() << endl;
02588 m_part->clearCaretRectIfNeeded();
02589 m_part->d->editor_context.m_selection.moveTo(Position(newFocusNode, 0L));
02590 m_part->setCaretVisible(true);
02591 } else {
02592 m_part->setCaretVisible(false);
02593 kDebug(6200) << "hide caret! fn: " << newFocusNode->nodeName().string() << endl;
02594 }
02595 m_part->notifySelectionChanged();
02596
02597 targetVisible = scrollTo(newFocusNode->getRect());
02598 }
02599
02600 if (targetVisible)
02601 {
02602
02603 d->tabMovePending = false;
02604
02605 m_part->xmlDocImpl()->setFocusNode(newFocusNode);
02606 if (newFocusNode)
02607 {
02608 Node guard(newFocusNode);
02609 if (!newFocusNode->hasOneRef() )
02610 {
02611 emit m_part->nodeActivated(Node(newFocusNode));
02612 }
02613 return true;
02614 }
02615 else
02616 {
02617 d->pseudoFocusNode = next?KHTMLViewPrivate::PFBottom:KHTMLViewPrivate::PFTop;
02618 return false;
02619 }
02620 }
02621 else
02622 {
02623 if (!d->tabMovePending)
02624 d->lastTabbingDirection = next;
02625 d->tabMovePending = true;
02626 return true;
02627 }
02628 }
02629
02630 void KHTMLView::displayAccessKeys()
02631 {
02632 QVector< QChar > taken;
02633 displayAccessKeys( NULL, this, taken, false );
02634 displayAccessKeys( NULL, this, taken, true );
02635 }
02636
02637 void KHTMLView::displayAccessKeys( KHTMLView* caller, KHTMLView* origview, QVector< QChar >& taken, bool use_fallbacks )
02638 {
02639 QMap< ElementImpl*, QChar > fallbacks;
02640 if( use_fallbacks )
02641 fallbacks = buildFallbackAccessKeys();
02642 for( NodeImpl* n = m_part->xmlDocImpl(); n != NULL; n = n->traverseNextNode()) {
02643 if( n->isElementNode()) {
02644 ElementImpl* en = static_cast< ElementImpl* >( n );
02645 DOMString s = en->getAttribute( ATTR_ACCESSKEY );
02646 QString accesskey;
02647 if( s.length() == 1 ) {
02648 QChar a = s.string()[ 0 ].toUpper();
02649 if( qFind( taken.begin(), taken.end(), a ) == taken.end())
02650 accesskey = a;
02651 }
02652 if( accesskey.isNull() && fallbacks.contains( en )) {
02653 QChar a = fallbacks[ en ].toUpper();
02654 if( qFind( taken.begin(), taken.end(), a ) == taken.end())
02655 accesskey = QString( "<qt><i>" ) + a + "</i></qt>";
02656 }
02657 if( !accesskey.isNull()) {
02658 QRect rec=en->getRect();
02659 QLabel *lab=new QLabel(accesskey,viewport());
02660 lab->setAttribute(Qt::WA_DeleteOnClose);
02661 connect( origview, SIGNAL(hideAccessKeys()), lab, SLOT(close()) );
02662 connect( this, SIGNAL(repaintAccessKeys()), lab, SLOT(repaint()));
02663 lab->setPalette(QToolTip::palette());
02664 lab->setLineWidth(2);
02665 lab->setFrameStyle(QFrame::Box | QFrame::Plain);
02666 lab->setMargin(3);
02667 lab->adjustSize();
02668 lab->setParent( widget() );
02669 lab->setAutoFillBackground(true);
02670 lab->move(
02671 qMin(rec.left()+rec.width()/2 - contentsX(), contentsWidth() - lab->width()),
02672 qMin(rec.top()+rec.height()/2 - contentsY(), contentsHeight() - lab->height()));
02673 lab->show();
02674 taken.append( accesskey[ 0 ] );
02675 }
02676 }
02677 }
02678 if( use_fallbacks )
02679 return;
02680
02681 QList<KParts::ReadOnlyPart*> frames = m_part->frames();
02682 foreach( KParts::ReadOnlyPart* cur, frames ) {
02683 if( !qobject_cast<KHTMLPart*>(cur) )
02684 continue;
02685 KHTMLPart* part = static_cast< KHTMLPart* >( cur );
02686 if( part->view() && part->view() != caller )
02687 part->view()->displayAccessKeys( this, origview, taken, use_fallbacks );
02688 }
02689
02690
02691 if (m_part->parentPart() && m_part->parentPart()->view()
02692 && m_part->parentPart()->view() != caller)
02693 m_part->parentPart()->view()->displayAccessKeys( this, origview, taken, use_fallbacks );
02694 }
02695
02696 bool KHTMLView::isScrollingFromMouseWheel() const
02697 {
02698 return d->scrollingFromWheel != QPoint(-1,-1);
02699 }
02700
02701 void KHTMLView::accessKeysTimeout()
02702 {
02703 d->accessKeysActivated=false;
02704 d->accessKeysPreActivate = false;
02705 m_part->setStatusBarText(QString(), KHTMLPart::BarOverrideText);
02706 emit hideAccessKeys();
02707 }
02708
02709
02710 bool KHTMLView::handleAccessKey( const QKeyEvent* ev )
02711 {
02712
02713
02714 QChar c;
02715 if( ev->key() >= Qt::Key_A && ev->key() <= Qt::Key_Z )
02716 c = 'A' + ev->key() - Qt::Key_A;
02717 else if( ev->key() >= Qt::Key_0 && ev->key() <= Qt::Key_9 )
02718 c = '0' + ev->key() - Qt::Key_0;
02719 else {
02720
02721
02722 if( ev->text().length() == 1 )
02723 c = ev->text()[ 0 ];
02724 }
02725 if( c.isNull())
02726 return false;
02727 return focusNodeWithAccessKey( c );
02728 }
02729
02730 bool KHTMLView::focusNodeWithAccessKey( QChar c, KHTMLView* caller )
02731 {
02732 DocumentImpl *doc = m_part->xmlDocImpl();
02733 if( !doc )
02734 return false;
02735 ElementImpl* node = doc->findAccessKeyElement( c );
02736 if( !node ) {
02737 QList<KParts::ReadOnlyPart*> frames = m_part->frames();
02738 foreach( KParts::ReadOnlyPart* cur, frames ) {
02739 if( !qobject_cast<KHTMLPart*>(cur) )
02740 continue;
02741 KHTMLPart* part = static_cast< KHTMLPart* >( cur );
02742 if( part->view() && part->view() != caller
02743 && part->view()->focusNodeWithAccessKey( c, this ))
02744 return true;
02745 }
02746
02747 if (m_part->parentPart() && m_part->parentPart()->view()
02748 && m_part->parentPart()->view() != caller
02749 && m_part->parentPart()->view()->focusNodeWithAccessKey( c, this ))
02750 return true;
02751 if( caller == NULL ) {
02752 const QMap< ElementImpl*, QChar > fallbacks = buildFallbackAccessKeys();
02753 for( QMap< ElementImpl*, QChar >::ConstIterator it = fallbacks.begin();
02754 it != fallbacks.end();
02755 ++it )
02756 if( *it == c ) {
02757 node = it.key();
02758 break;
02759 }
02760 }
02761 if( node == NULL )
02762 return false;
02763 }
02764
02765
02766
02767 QRect r = node->getRect();
02768 ensureVisible( r.right(), r.bottom());
02769 ensureVisible( r.left(), r.top());
02770
02771 Node guard( node );
02772 if( node->isFocusable()) {
02773 if (node->id()==ID_LABEL) {
02774
02775 node=static_cast<ElementImpl *>(static_cast< HTMLLabelElementImpl* >( node )->getFormElement());
02776 if (!node) return true;
02777 guard = node;
02778 }
02779
02780 #ifdef __GNUC__
02781 #warning "port QFocusEvent::setReason( QFocusEvent::Shortcut ); to qt4"
02782 #endif
02783
02784 m_part->xmlDocImpl()->setFocusNode(node);
02785 #ifdef __GNUC__
02786 #warning "port QFocusEvent::resetReason(); to qt4"
02787 #endif
02788
02789 if( node != NULL && node->hasOneRef())
02790 return true;
02791 emit m_part->nodeActivated(Node(node));
02792 if( node != NULL && node->hasOneRef())
02793 return true;
02794 }
02795
02796 switch( node->id()) {
02797 case ID_A:
02798 static_cast< HTMLAnchorElementImpl* >( node )->click();
02799 break;
02800 case ID_INPUT:
02801 static_cast< HTMLInputElementImpl* >( node )->click();
02802 break;
02803 case ID_BUTTON:
02804 static_cast< HTMLButtonElementImpl* >( node )->click();
02805 break;
02806 case ID_AREA:
02807 static_cast< HTMLAreaElementImpl* >( node )->click();
02808 break;
02809 case ID_TEXTAREA:
02810 break;
02811 case ID_LEGEND:
02812
02813 break;
02814 }
02815 return true;
02816 }
02817
02818 static QString getElementText( NodeImpl* start, bool after )
02819 {
02820 QString ret;
02821 for( NodeImpl* n = after ? start->nextSibling() : start->traversePreviousNode();
02822 n != NULL;
02823 n = after ? n->traverseNextNode() : n->traversePreviousNode()) {
02824 if( n->isTextNode()) {
02825 if( after )
02826 ret += static_cast< TextImpl* >( n )->toString().string();
02827 else
02828 ret.prepend( static_cast< TextImpl* >( n )->toString().string());
02829 } else {
02830 switch( n->id()) {
02831 case ID_A:
02832 case ID_FONT:
02833 case ID_TT:
02834 case ID_U:
02835 case ID_B:
02836 case ID_I:
02837 case ID_S:
02838 case ID_STRIKE:
02839 case ID_BIG:
02840 case ID_SMALL:
02841 case ID_EM:
02842 case ID_STRONG:
02843 case ID_DFN:
02844 case ID_CODE:
02845 case ID_SAMP:
02846 case ID_KBD:
02847 case ID_VAR:
02848 case ID_CITE:
02849 case ID_ABBR:
02850 case ID_ACRONYM:
02851 case ID_SUB:
02852 case ID_SUP:
02853 case ID_SPAN:
02854 case ID_NOBR:
02855 case ID_WBR:
02856 break;
02857 case ID_TD:
02858 if( ret.trimmed().isEmpty())
02859 break;
02860
02861 default:
02862 return ret.simplified();
02863 }
02864 }
02865 }
02866 return ret.simplified();
02867 }
02868
02869 static QMap< NodeImpl*, QString > buildLabels( NodeImpl* start )
02870 {
02871 QMap< NodeImpl*, QString > ret;
02872 for( NodeImpl* n = start;
02873 n != NULL;
02874 n = n->traverseNextNode()) {
02875 if( n->id() == ID_LABEL ) {
02876 HTMLLabelElementImpl* label = static_cast< HTMLLabelElementImpl* >( n );
02877 NodeImpl* labelfor = label->getFormElement();
02878 if( labelfor )
02879 ret[ labelfor ] = label->innerText().string().simplified();
02880 }
02881 }
02882 return ret;
02883 }
02884
02885 namespace khtml {
02886 struct AccessKeyData {
02887 ElementImpl* element;
02888 QString text;
02889 QString url;
02890 int priority;
02891 };
02892 }
02893
02894 QMap< ElementImpl*, QChar > KHTMLView::buildFallbackAccessKeys() const
02895 {
02896
02897 QLinkedList< AccessKeyData > data;
02898
02899 QMap< NodeImpl*, QString > labels = buildLabels( m_part->xmlDocImpl());
02900 for( NodeImpl* n = m_part->xmlDocImpl();
02901 n != NULL;
02902 n = n->traverseNextNode()) {
02903 if( n->isElementNode()) {
02904 ElementImpl* element = static_cast< ElementImpl* >( n );
02905 if( element->getAttribute( ATTR_ACCESSKEY ).length() == 1 )
02906 continue;
02907 if( element->renderer() == NULL )
02908 continue;
02909 QString text;
02910 QString url;
02911 int priority = 0;
02912 bool ignore = false;
02913 bool text_after = false;
02914 bool text_before = false;
02915 switch( element->id()) {
02916 case ID_A:
02917 url = khtml::parseURL(element->getAttribute(ATTR_HREF)).string();
02918 if( url.isEmpty())
02919 continue;
02920 text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplified();
02921 priority = 2;
02922 break;
02923 case ID_INPUT: {
02924 HTMLInputElementImpl* in = static_cast< HTMLInputElementImpl* >( element );
02925 switch( in->inputType()) {
02926 case HTMLInputElementImpl::SUBMIT:
02927 text = in->value().string();
02928 if( text.isEmpty())
02929 text = i18n( "Submit" );
02930 priority = 7;
02931 break;
02932 case HTMLInputElementImpl::IMAGE:
02933 text = in->altText().string();
02934 priority = 7;
02935 break;
02936 case HTMLInputElementImpl::BUTTON:
02937 text = in->value().string();
02938 priority = 5;
02939 break;
02940 case HTMLInputElementImpl::RESET:
02941 text = in->value().string();
02942 if( text.isEmpty())
02943 text = i18n( "Reset" );
02944 priority = 5;
02945 break;
02946 case HTMLInputElementImpl::HIDDEN:
02947 ignore = true;
02948 break;
02949 case HTMLInputElementImpl::CHECKBOX:
02950 case HTMLInputElementImpl::RADIO:
02951 text_after = true;
02952 priority = 5;
02953 break;
02954 case HTMLInputElementImpl::TEXT:
02955 case HTMLInputElementImpl::PASSWORD:
02956 case HTMLInputElementImpl::FILE:
02957 text_before = true;
02958 priority = 5;
02959 break;
02960 default:
02961 priority = 5;
02962 break;
02963 }
02964 break;
02965 }
02966 case ID_BUTTON:
02967 text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplified();
02968 switch( static_cast< HTMLButtonElementImpl* >( element )->buttonType()) {
02969 case HTMLButtonElementImpl::SUBMIT:
02970 if( text.isEmpty())
02971 text = i18n( "Submit" );
02972 priority = 7;
02973 break;
02974 case HTMLButtonElementImpl::RESET:
02975 if( text.isEmpty())
02976 text = i18n( "Reset" );
02977 priority = 5;
02978 break;
02979 default:
02980 priority = 5;
02981 break;
02982 }
02983 break;
02984 case ID_SELECT:
02985 text_before = true;
02986 text_after = true;
02987 priority = 5;
02988 break;
02989 case ID_FRAME:
02990 ignore = true;
02991 break;
02992 default:
02993 ignore = !element->isFocusable();
02994 priority = 2;
02995 break;
02996 }
02997 if( ignore )
02998 continue;
02999 if( text.isNull() && labels.contains( element ))
03000 text = labels[ element ];
03001 if( text.isNull() && text_before )
03002 text = getElementText( element, false );
03003 if( text.isNull() && text_after )
03004 text = getElementText( element, true );
03005 text = text.trimmed();
03006
03007 const QList< QPair< QString, QChar > > priorities
03008 = m_part->settings()->fallbackAccessKeysAssignments();
03009 for( QList< QPair< QString, QChar > >::ConstIterator it = priorities.begin();
03010 it != priorities.end();
03011 ++it ) {
03012 if( text == (*it).first )
03013 priority = 10;
03014 }
03015 AccessKeyData tmp = { element, text, url, priority };
03016 data.append( tmp );
03017 }
03018 }
03019
03020 QList< QChar > keys;
03021 for( char c = 'A'; c <= 'Z'; ++c )
03022 keys << c;
03023 for( char c = '0'; c <= '9'; ++c )
03024 keys << c;
03025 for( NodeImpl* n = m_part->xmlDocImpl();
03026 n != NULL;
03027 n = n->traverseNextNode()) {
03028 if( n->isElementNode()) {
03029 ElementImpl* en = static_cast< ElementImpl* >( n );
03030 DOMString s = en->getAttribute( ATTR_ACCESSKEY );
03031 if( s.length() == 1 ) {
03032 QChar c = s.string()[ 0 ].toUpper();
03033 keys.removeAll( c );
03034 }
03035 }
03036 }
03037
03038 QMap< ElementImpl*, QChar > ret;
03039 for( int priority = 10; priority >= 0; --priority ) {
03040 for( QLinkedList< AccessKeyData >::Iterator it = data.begin();
03041 it != data.end();
03042 ) {
03043 if( (*it).priority != priority ) {
03044 ++it;
03045 continue;
03046 }
03047 if( keys.isEmpty())
03048 break;
03049 QString text = (*it).text;
03050 QChar key;
03051 if( key.isNull() && !text.isEmpty()) {
03052 const QList< QPair< QString, QChar > > priorities
03053 = m_part->settings()->fallbackAccessKeysAssignments();
03054 for( QList< QPair< QString, QChar > >::ConstIterator it = priorities.begin();
03055 it != priorities.end();
03056 ++it )
03057 if( text == (*it).first && keys.contains( (*it).second )) {
03058 key = (*it).second;
03059 break;
03060 }
03061 }
03062
03063
03064
03065 if( key.isNull() && !text.isEmpty()) {
03066 const QStringList words = text.split( ' ' );
03067 for( QStringList::ConstIterator it = words.begin();
03068 it != words.end();
03069 ++it ) {
03070 if( keys.contains( (*it)[ 0 ].toUpper())) {
03071 key = (*it)[ 0 ].toUpper();
03072 break;
03073 }
03074 }
03075 }
03076 if( key.isNull() && !text.isEmpty()) {
03077 for( int i = 0; i < text.length(); ++i ) {
03078 if( keys.contains( text[ i ].toUpper())) {
03079 key = text[ i ].toUpper();
03080 break;
03081 }
03082 }
03083 }
03084 if( key.isNull())
03085 key = keys.front();
03086 ret[ (*it).element ] = key;
03087 keys.removeAll( key );
03088 QString url = (*it).url;
03089 it = data.erase( it );
03090
03091 if( !url.isEmpty() && !url.startsWith( "javascript:", Qt::CaseInsensitive )) {
03092 for( QLinkedList< AccessKeyData >::Iterator it2 = data.begin();
03093 it2 != data.end();
03094 ) {
03095 if( (*it2).url == url ) {
03096 ret[ (*it2).element ] = key;
03097 if( it == it2 )
03098 ++it;
03099 it2 = data.erase( it2 );
03100 } else
03101 ++it2;
03102 }
03103 }
03104 }
03105 }
03106 return ret;
03107 }
03108
03109 void KHTMLView::setMediaType( const QString &medium )
03110 {
03111 m_medium = medium;
03112 }
03113
03114 QString KHTMLView::mediaType() const
03115 {
03116 return m_medium;
03117 }
03118
03119 bool KHTMLView::pagedMode() const
03120 {
03121 return d->paged;
03122 }
03123
03124 void KHTMLView::setWidgetVisible(RenderWidget* w, bool vis)
03125 {
03126 if (vis) {
03127 d->visibleWidgets.insert(w, w->widget());
03128 }
03129 else
03130 d->visibleWidgets.remove(w);
03131 }
03132
03133 bool KHTMLView::needsFullRepaint() const
03134 {
03135 return d->needsFullRepaint;
03136 }
03137
03138 namespace {
03139 class QPointerDeleter
03140 {
03141 public:
03142 explicit QPointerDeleter(QObject* o) : obj(o) {}
03143 ~QPointerDeleter() { delete obj; }
03144 private:
03145 const QPointer<QObject> obj;
03146 };
03147 }
03148
03149 void KHTMLView::print(bool quick)
03150 {
03151 if(!m_part->xmlDocImpl()) return;
03152 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
03153 if(!root) return;
03154
03155 QPointer<KHTMLPrintSettings> printSettings(new KHTMLPrintSettings);
03156
03157
03158 KSharedConfigPtr config = KGlobal::config();
03159 KConfigGroup group(config, "KHTML Print Settings");
03160 printSettings->setprintFriendly(group.readEntry("PrintFriendly", true));
03161 printSettings->setprintImages(group.readEntry("PrintImages", true));
03162 printSettings->setprintHeader(group.readEntry("PrintHeader", true));
03163
03164 const QPointerDeleter settingsDeleter(printSettings);
03165 QPrinter printer;
03166 QPointer<QPrintDialog> dialog = KdePrint::createPrintDialog(&printer, QList<QWidget*>() << printSettings, this);
03167 dialog->setOption( QAbstractPrintDialog::PrintPageRange, false);
03168 const QPointerDeleter dialogDeleter(dialog);
03169
03170 QString docname = m_part->xmlDocImpl()->URL().prettyUrl();
03171 if ( !docname.isEmpty() )
03172 docname = KStringHandler::csqueeze(docname, 80);
03173
03174 if(quick || (dialog->exec() && dialog)) {
03175
03176 KSharedConfigPtr config = KGlobal::config();
03177 KConfigGroup group(config, "KHTML Print Settings");
03178 group.writeEntry("PrintFriendly", printSettings->printFriendly());
03179 group.writeEntry("PrintImages", printSettings->printImages());
03180 group.writeEntry("PrintHeader", printSettings->printHeader());
03181
03182 viewport()->setCursor( Qt::WaitCursor );
03183
03184 printer.setFullPage(false);
03185 printer.setCreator(QString("KDE %1.%2.%3 HTML Library").arg(KDE_VERSION_MAJOR).arg(KDE_VERSION_MINOR).arg(KDE_VERSION_RELEASE));
03186 printer.setDocName(docname);
03187
03188 QPainter *p = new QPainter;
03189 p->begin( &printer );
03190 khtml::setPrintPainter( p );
03191
03192 m_part->xmlDocImpl()->setPaintDevice( &printer );
03193 QString oldMediaType = mediaType();
03194 setMediaType( "print" );
03195
03196
03197
03198 m_part->xmlDocImpl()->setPrintStyleSheet( printSettings->printFriendly() ?
03199 "* { background-image: none !important;"
03200 " background-color: white !important;"
03201 " color: black !important; }"
03202 "body { margin: 0px !important; }"
03203 "html { margin: 0px !important; }" :
03204 "body { margin: 0px !important; }"
03205 "html { margin: 0px !important; }"
03206 );
03207
03208 kDebug(6000) << "printing: physical page width = " << printer.width()
03209 << " height = " << printer.height() << endl;
03210 root->setStaticMode(true);
03211 root->setPagedMode(true);
03212 root->setWidth(printer.width());
03213
03214 root->setPageTop(0);
03215 root->setPageBottom(0);
03216 d->paged = true;
03217
03218 m_part->xmlDocImpl()->styleSelector()->computeFontSizes(printer.logicalDpiY(), 100);
03219 m_part->xmlDocImpl()->updateStyleSelector();
03220 root->setPrintImages(printSettings->printImages());
03221 root->makePageBreakAvoidBlocks();
03222
03223 root->setNeedsLayoutAndMinMaxRecalc();
03224 root->layout();
03225
03226
03227
03228 bool printHeader = printSettings->printHeader();
03229
03230 int headerHeight = 0;
03231 QFont headerFont("Sans Serif", 8);
03232
03233 QString headerLeft = KGlobal::locale()->formatDate(QDate::currentDate(),KLocale::ShortDate);
03234 QString headerMid = docname;
03235 QString headerRight;
03236
03237 if (printHeader)
03238 {
03239 p->setFont(headerFont);
03240 headerHeight = (p->fontMetrics().lineSpacing() * 3) / 2;
03241 }
03242
03243
03244 kDebug(6000) << "printing: html page width = " << root->docWidth()
03245 << " height = " << root->docHeight() << endl;
03246 kDebug(6000) << "printing: margins left = " << printer.pageRect().left() - printer.paperRect().left()
03247 << " top = " << printer.pageRect().top() - printer.paperRect().top() << endl;
03248 kDebug(6000) << "printing: paper width = " << printer.width()
03249 << " height = " << printer.height() << endl;
03250
03251
03252 int pageWidth = printer.width();
03253 int pageHeight = printer.height();
03254 p->setClipRect(0,0, pageWidth, pageHeight);
03255
03256 pageHeight -= headerHeight;
03257
03258 bool scalePage = false;
03259 double scale = 0.0;
03260 #ifndef QT_NO_TRANSFORMATIONS
03261 if(root->docWidth() > printer.width()) {
03262 scalePage = true;
03263 scale = ((double) printer.width())/((double) root->docWidth());
03264 pageHeight = (int) (pageHeight/scale);
03265 pageWidth = (int) (pageWidth/scale);
03266 headerHeight = (int) (headerHeight/scale);
03267 }
03268 #endif
03269 kDebug(6000) << "printing: scaled html width = " << pageWidth
03270 << " height = " << pageHeight << endl;
03271
03272 root->setHeight(pageHeight);
03273 root->setPageBottom(pageHeight);
03274 root->setNeedsLayout(true);
03275 root->layoutIfNeeded();
03276
03277
03278
03279 if (printHeader)
03280 {
03281 int available_width = printer.width() - 10 -
03282 2 * qMax(p->boundingRect(0, 0, printer.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerLeft).width(),
03283 p->boundingRect(0, 0, printer.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerRight).width());
03284 if (available_width < 150)
03285 available_width = 150;
03286 int mid_width;
03287 int squeeze = 120;
03288 do {
03289 headerMid = KStringHandler::csqueeze(docname, squeeze);
03290 mid_width = p->boundingRect(0, 0, printer.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerMid).width();
03291 squeeze -= 10;
03292 } while (mid_width > available_width);
03293 }
03294
03295 int top = 0;
03296 int bottom = 0;
03297 int page = 1;
03298 while(top < root->docHeight()) {
03299 if(top > 0) printer.newPage();
03300 p->save();
03301 p->setClipRect(0, 0, pageWidth, headerHeight);
03302 if (printHeader)
03303 {
03304 int dy = p->fontMetrics().lineSpacing();
03305 p->setPen(Qt::black);
03306 p->setFont(headerFont);
03307
03308 headerRight = QString("#%1").arg(page);
03309
03310 p->drawText(0, 0, printer.width(), dy, Qt::AlignLeft, headerLeft);
03311 p->drawText(0, 0, printer.width(), dy, Qt::AlignHCenter, headerMid);
03312 p->drawText(0, 0, printer.width(), dy, Qt::AlignRight, headerRight);
03313 }
03314
03315 #ifndef QT_NO_TRANSFORMATIONS
03316 if (scalePage)
03317 p->scale(scale, scale);
03318 #endif
03319 p->restore();
03320 p->translate(0, headerHeight-top);
03321
03322 bottom = top+pageHeight;
03323
03324 root->setPageTop(top);
03325 root->setPageBottom(bottom);
03326 root->setPageNumber(page);
03327
03328 root->layer()->paint(p, QRect(0, top, pageWidth, pageHeight));
03329 kDebug(6000) << "printed: page " << page <<" bottom At = " << bottom;
03330
03331 top = bottom;
03332 p->resetTransform();
03333 page++;
03334 }
03335
03336 p->end();
03337 delete p;
03338
03339
03340 root->setPagedMode(false);
03341 root->setStaticMode(false);
03342 d->paged = false;
03343 khtml::setPrintPainter( 0 );
03344 setMediaType( oldMediaType );
03345 m_part->xmlDocImpl()->setPaintDevice( this );
03346 m_part->xmlDocImpl()->styleSelector()->computeFontSizes(m_part->xmlDocImpl()->logicalDpiY(), m_part->fontScaleFactor());
03347 m_part->xmlDocImpl()->updateStyleSelector();
03348 viewport()->unsetCursor();
03349 }
03350 }
03351
03352 void KHTMLView::slotPaletteChanged()
03353 {
03354 if(!m_part->xmlDocImpl()) return;
03355 DOM::DocumentImpl *document = m_part->xmlDocImpl();
03356 if (!document->isHTMLDocument()) return;
03357 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(document->renderer());
03358 if(!root) return;
03359 root->style()->resetPalette();
03360 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
03361 if(!body) return;
03362 body->setChanged(true);
03363 body->recalcStyle( NodeImpl::Force );
03364 }
03365
03366 void KHTMLView::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
03367 {
03368 if(!m_part->xmlDocImpl()) return;
03369 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
03370 if(!root) return;
03371 d->firstRepaintPending = false;
03372
03373 QPaintDevice* opd = m_part->xmlDocImpl()->paintDevice();
03374 m_part->xmlDocImpl()->setPaintDevice(p->device());
03375 root->setPagedMode(true);
03376 root->setStaticMode(true);
03377 root->setWidth(rc.width());
03378
03379
03380 QRegion creg = p->clipRegion();
03381 QTransform t = p->worldTransform();
03382 QRect w = p->window();
03383 QRect v = p->viewport();
03384 bool vte = p->viewTransformEnabled();
03385 bool wme = p->worldMatrixEnabled();
03386
03387 p->setClipRect(rc);
03388 p->translate(rc.left(), rc.top());
03389 double scale = ((double) rc.width()/(double) root->docWidth());
03390 int height = (int) ((double) rc.height() / scale);
03391 #ifndef QT_NO_TRANSFORMATIONS
03392 p->scale(scale, scale);
03393 #endif
03394 root->setPageTop(yOff);
03395 root->setPageBottom(yOff+height);
03396
03397 root->layer()->paint(p, QRect(0, yOff, root->docWidth(), height));
03398 if (more)
03399 *more = yOff + height < root->docHeight();
03400
03401
03402 p->setWorldTransform(t);
03403 p->setWindow(w);
03404 p->setViewport(v);
03405 p->setViewTransformEnabled( vte );
03406 p->setWorldMatrixEnabled( wme );
03407 if (!creg.isEmpty())
03408 p->setClipRegion( creg );
03409 else
03410 p->setClipRegion(QRegion(), Qt::NoClip);
03411
03412 root->setPagedMode(false);
03413 root->setStaticMode(false);
03414 m_part->xmlDocImpl()->setPaintDevice( opd );
03415 }
03416
03417 void KHTMLView::render(QPainter* p, const QRect& r, const QPoint& off)
03418 {
03419 d->firstRepaintPending = false;
03420 QRect clip(off.x()+r.x(), off.y()+r.y(),r.width(),r.height());
03421 if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
03422 p->fillRect(clip, palette().brush(QPalette::Active, QPalette::Base));
03423 return;
03424 }
03425 QPaintDevice* opd = m_part->xmlDocImpl()->paintDevice();
03426 m_part->xmlDocImpl()->setPaintDevice(p->device());
03427
03428
03429 QRegion creg = p->clipRegion();
03430 QTransform t = p->worldTransform();
03431 QRect w = p->window();
03432 QRect v = p->viewport();
03433 bool vte = p->viewTransformEnabled();
03434 bool wme = p->worldMatrixEnabled();
03435
03436 p->setClipRect(clip);
03437 QRect rect = r.translated(contentsX(),contentsY());
03438 p->translate(off.x()-contentsX(), off.y()-contentsY());
03439
03440 m_part->xmlDocImpl()->renderer()->layer()->paint(p, rect);
03441
03442
03443 p->setWorldTransform(t);
03444 p->setWindow(w);
03445 p->setViewport(v);
03446 p->setViewTransformEnabled( vte );
03447 p->setWorldMatrixEnabled( wme );
03448 if (!creg.isEmpty())
03449 p->setClipRegion( creg );
03450 else
03451 p->setClipRegion(QRegion(), Qt::NoClip);
03452
03453 m_part->xmlDocImpl()->setPaintDevice( opd );
03454 }
03455
03456 void KHTMLView::setHasStaticBackground(bool partial)
03457 {
03458
03459 if (d->staticWidget == KHTMLViewPrivate::SBFull && m_kwp->isRedirected())
03460 return;
03461
03462 d->staticWidget = partial ?
03463 KHTMLViewPrivate::SBPartial : KHTMLViewPrivate::SBFull;
03464 }
03465
03466 void KHTMLView::setHasNormalBackground()
03467 {
03468
03469 if (d->staticWidget == KHTMLViewPrivate::SBFull && m_kwp->isRedirected())
03470 return;
03471
03472 d->staticWidget = KHTMLViewPrivate::SBNone;
03473 }
03474
03475 void KHTMLView::addStaticObject(bool fixed)
03476 {
03477 if (fixed)
03478 d->fixedObjectsCount++;
03479 else
03480 d->staticObjectsCount++;
03481
03482 setHasStaticBackground( true );
03483 }
03484
03485 void KHTMLView::removeStaticObject(bool fixed)
03486 {
03487 if (fixed)
03488 d->fixedObjectsCount--;
03489 else
03490 d->staticObjectsCount--;
03491
03492 assert( d->fixedObjectsCount >= 0 && d->staticObjectsCount >= 0 );
03493
03494 if (!d->staticObjectsCount && !d->fixedObjectsCount)
03495 setHasNormalBackground();
03496 else
03497 setHasStaticBackground( true );
03498 }
03499
03500 void KHTMLView::setVerticalScrollBarPolicy( Qt::ScrollBarPolicy policy )
03501 {
03502 #ifndef KHTML_NO_SCROLLBARS
03503 d->vpolicy = policy;
03504 QScrollArea::setVerticalScrollBarPolicy(policy);
03505 #else
03506 Q_UNUSED( policy );
03507 #endif
03508 }
03509
03510 void KHTMLView::setHorizontalScrollBarPolicy( Qt::ScrollBarPolicy policy )
03511 {
03512 #ifndef KHTML_NO_SCROLLBARS
03513 d->hpolicy = policy;
03514 QScrollArea::setHorizontalScrollBarPolicy(policy);
03515 #else
03516 Q_UNUSED( policy );
03517 #endif
03518 }
03519
03520 void KHTMLView::restoreScrollBar()
03521 {
03522 int ow = visibleWidth();
03523 QScrollArea::setVerticalScrollBarPolicy(d->vpolicy);
03524 if (visibleWidth() != ow)
03525 layout();
03526 d->prevScrollbarVisible = verticalScrollBar()->isVisible();
03527 }
03528
03529 QStringList KHTMLView::formCompletionItems(const QString &name) const
03530 {
03531 if (!m_part->settings()->isFormCompletionEnabled())
03532 return QStringList();
03533 if (!d->formCompletions)
03534 d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions"));
03535 return d->formCompletions->group("").readEntry(name, QStringList());
03536 }
03537
03538 void KHTMLView::clearCompletionHistory(const QString& name)
03539 {
03540 if (!d->formCompletions)
03541 {
03542 d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions"));
03543 }
03544 d->formCompletions->group("").writeEntry(name, "");
03545 d->formCompletions->sync();
03546 }
03547
03548 void KHTMLView::addFormCompletionItem(const QString &name, const QString &value)
03549 {
03550 if (!m_part->settings()->isFormCompletionEnabled())
03551 return;
03552
03553
03554
03555 bool cc_number(true);
03556 for ( int i = 0; i < value.length(); ++i)
03557 {
03558 QChar c(value[i]);
03559 if (!c.isNumber() && c != '-' && !c.isSpace())
03560 {
03561 cc_number = false;
03562 break;
03563 }
03564 }
03565 if (cc_number)
03566 return;
03567 QStringList items = formCompletionItems(name);
03568 if (!items.contains(value))
03569 items.prepend(value);
03570 while ((int)items.count() > m_part->settings()->maxFormCompletionItems())
03571 items.erase(items.isEmpty() ? items.end() : --items.end());
03572 d->formCompletions->group("").writeEntry(name, items);
03573 }
03574
03575 void KHTMLView::addNonPasswordStorableSite(const QString& host)
03576 {
03577 if (!d->formCompletions) {
03578 d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions"));
03579 }
03580
03581 KConfigGroup cg( d->formCompletions, "NonPasswordStorableSites");
03582 QStringList sites = cg.readEntry("Sites", QStringList());
03583 sites.append(host);
03584 cg.writeEntry("Sites", sites);
03585 cg.sync();
03586 }
03587
03588
03589 void KHTMLView::delNonPasswordStorableSite(const QString& host)
03590 {
03591 if (!d->formCompletions) {
03592 d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions"));
03593 }
03594
03595 KConfigGroup cg( d->formCompletions, "NonPasswordStorableSites");
03596 QStringList sites = cg.readEntry("Sites", QStringList());
03597 sites.removeOne(host);
03598 cg.writeEntry("Sites", sites);
03599 cg.sync();
03600 }
03601
03602 bool KHTMLView::nonPasswordStorableSite(const QString& host) const
03603 {
03604 if (!d->formCompletions) {
03605 d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions"));
03606 }
03607 QStringList sites = d->formCompletions->group( "NonPasswordStorableSites" ).readEntry("Sites", QStringList());
03608 return (sites.indexOf(host) != -1);
03609 }
03610
03611
03612 bool KHTMLView::dispatchMouseEvent(int eventId, DOM::NodeImpl *targetNode,
03613 DOM::NodeImpl *targetNodeNonShared, bool cancelable,
03614 int detail,QMouseEvent *_mouse, bool setUnder,
03615 int mouseEventType, int orient)
03616 {
03617
03618 if (targetNode && targetNode->isTextNode())
03619 targetNode = targetNode->parentNode();
03620
03621 if (d->underMouse)
03622 d->underMouse->deref();
03623 d->underMouse = targetNode;
03624 if (d->underMouse)
03625 d->underMouse->ref();
03626
03627 if (d->underMouseNonShared)
03628 d->underMouseNonShared->deref();
03629 d->underMouseNonShared = targetNodeNonShared;
03630 if (d->underMouseNonShared)
03631 d->underMouseNonShared->ref();
03632
03633 bool isWheelEvent = (mouseEventType == DOM::NodeImpl::MouseWheel);
03634
03635 int exceptioncode = 0;
03636 int pageX = _mouse->x();
03637 int pageY = _mouse->y();
03638 revertTransforms(pageX, pageY);
03639 int clientX = pageX - contentsX();
03640 int clientY = pageY - contentsY();
03641 int screenX = _mouse->globalX();
03642 int screenY = _mouse->globalY();
03643 int button = -1;
03644 switch (_mouse->button()) {
03645 case Qt::LeftButton:
03646 button = 0;
03647 break;
03648 case Qt::MidButton:
03649 button = 1;
03650 break;
03651 case Qt::RightButton:
03652 button = 2;
03653 break;
03654 default:
03655 break;
03656 }
03657 if (d->accessKeysEnabled && d->accessKeysPreActivate && button!=-1)
03658 d->accessKeysPreActivate=false;
03659
03660 bool ctrlKey = (_mouse->modifiers() & Qt::ControlModifier);
03661 bool altKey = (_mouse->modifiers() & Qt::AltModifier);
03662 bool shiftKey = (_mouse->modifiers() & Qt::ShiftModifier);
03663 bool metaKey = (_mouse->modifiers() & Qt::MetaModifier);
03664
03665
03666 if (setUnder && d->oldUnderMouse != targetNode) {
03667 if (d->oldUnderMouse && d->oldUnderMouse->document() != m_part->xmlDocImpl()) {
03668 d->oldUnderMouse->deref();
03669 d->oldUnderMouse = 0;
03670 }
03671
03672 if (d->oldUnderMouse) {
03673
03674 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOUT_EVENT,
03675 true,true,m_part->xmlDocImpl()->defaultView(),
03676 0,screenX,screenY,clientX,clientY,pageX, pageY,
03677 ctrlKey,altKey,shiftKey,metaKey,
03678 button,targetNode);
03679 me->ref();
03680 d->oldUnderMouse->dispatchEvent(me,exceptioncode,true);
03681 me->deref();
03682 }
03683
03684 if (targetNode) {
03685 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOVER_EVENT,
03686 true,true,m_part->xmlDocImpl()->defaultView(),
03687 0,screenX,screenY,clientX,clientY,pageX, pageY,
03688 ctrlKey,altKey,shiftKey,metaKey,
03689 button,d->oldUnderMouse);
03690
03691 me->ref();
03692 targetNode->dispatchEvent(me,exceptioncode,true);
03693 me->deref();
03694 }
03695 if (d->oldUnderMouse)
03696 d->oldUnderMouse->deref();
03697 d->oldUnderMouse = targetNode;
03698 if (d->oldUnderMouse)
03699 d->oldUnderMouse->ref();
03700 }
03701
03702 bool swallowEvent = false;
03703
03704 if (targetNode) {
03705
03706 if (targetNode->isGenericFormElement()
03707 && static_cast<HTMLGenericFormElementImpl*>(targetNode)->disabled())
03708 return true;
03709
03710
03711 bool dblclick = ( eventId == EventImpl::CLICK_EVENT &&
03712 _mouse->type() == QEvent::MouseButtonDblClick );
03713 MouseEventImpl *me = new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
03714 true,cancelable,m_part->xmlDocImpl()->defaultView(),
03715 detail,screenX,screenY,clientX,clientY,pageX, pageY,
03716 ctrlKey,altKey,shiftKey,metaKey,
03717 button,0, isWheelEvent ? 0 : _mouse, dblclick,
03718 isWheelEvent ? static_cast<MouseEventImpl::Orientation>(orient) : MouseEventImpl::ONone );
03719 me->ref();
03720 if ( !d->m_mouseEventsTarget && RenderLayer::gScrollBar && eventId == EventImpl::MOUSEDOWN_EVENT )
03721
03722 d->m_mouseEventsTarget = RenderLayer::gScrollBar;
03723 if ( d->m_mouseEventsTarget && qobject_cast<QScrollBar*>(d->m_mouseEventsTarget) &&
03724 dynamic_cast<KHTMLWidget*>(static_cast<QWidget*>(d->m_mouseEventsTarget)) ) {
03725
03726
03727 KHTMLWidget*w = dynamic_cast<KHTMLWidget*>(static_cast<QWidget*>(d->m_mouseEventsTarget));
03728 QPoint p = w->m_kwp->absolutePos();
03729 QMouseEvent fw(_mouse->type(), QPoint(pageX, pageY)-p, _mouse->button(), _mouse->buttons(), _mouse->modifiers());
03730 static_cast<RenderWidget::EventPropagator *>(static_cast<QWidget*>(d->m_mouseEventsTarget))->sendEvent(&fw);
03731 if (_mouse->type() == QMouseEvent::MouseButtonPress && _mouse->button() == Qt::RightButton) {
03732 QContextMenuEvent cme(QContextMenuEvent::Mouse, p);
03733 static_cast<RenderWidget::EventPropagator *>(static_cast<QWidget*>(d->m_mouseEventsTarget))->sendEvent(&cme);
03734 d->m_mouseEventsTarget = 0;
03735 }
03736 swallowEvent = true;
03737 } else {
03738 targetNode->dispatchEvent(me,exceptioncode,true);
03739 bool defaultHandled = me->defaultHandled();
03740 if (defaultHandled || me->defaultPrevented())
03741 swallowEvent = true;
03742 }
03743 if (eventId == EventImpl::MOUSEDOWN_EVENT && !me->defaultPrevented()) {
03744
03745
03746
03747
03748 DOM::NodeImpl* nodeImpl = targetNode;
03749 for ( ; nodeImpl && !nodeImpl->isFocusable(); nodeImpl = nodeImpl->parentNode())
03750 {}
03751 if (nodeImpl && nodeImpl->isMouseFocusable())
03752 m_part->xmlDocImpl()->setFocusNode(nodeImpl);
03753 else if (!nodeImpl || !nodeImpl->focused())
03754 m_part->xmlDocImpl()->setFocusNode(0);
03755 }
03756 me->deref();
03757 }
03758
03759 return swallowEvent;
03760 }
03761
03762 void KHTMLView::setIgnoreWheelEvents( bool e )
03763 {
03764 d->ignoreWheelEvents = e;
03765 }
03766
03767 #ifndef QT_NO_WHEELEVENT
03768
03769 void KHTMLView::wheelEvent(QWheelEvent* e)
03770 {
03771
03772
03773 if (d->scrollingFromWheel != QPoint(-1,-1) && d->scrollingFromWheel != QCursor::pos())
03774 d->scrollingFromWheel = d->scrollingFromWheelTimerId ? QCursor::pos() : QPoint(-1,-1);
03775
03776 if (d->accessKeysEnabled && d->accessKeysPreActivate) d->accessKeysPreActivate=false;
03777
03778 if ( ( e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier )
03779 {
03780 emit zoomView( - e->delta() );
03781 e->accept();
03782 }
03783 else if (d->firstLayoutPending)
03784 {
03785 e->accept();
03786 }
03787 else if( !m_kwp->isRedirected() &&
03788 ( (e->orientation() == Qt::Vertical &&
03789 ((d->ignoreWheelEvents && !verticalScrollBar()->isVisible())
03790 || (e->delta() > 0 && contentsY() <= 0)
03791 || (e->delta() < 0 && contentsY() >= contentsHeight() - visibleHeight())))
03792 ||
03793 (e->orientation() == Qt::Horizontal &&
03794 ((d->ignoreWheelEvents && !horizontalScrollBar()->isVisible())
03795 || (e->delta() > 0 && contentsX() <=0)
03796 || (e->delta() < 0 && contentsX() >= contentsWidth() - visibleWidth()))))
03797 && m_part->parentPart())
03798 {
03799 if ( m_part->parentPart()->view() )
03800 m_part->parentPart()->view()->wheelEvent( e );
03801 e->ignore();
03802 }
03803 else
03804 {
03805 int xm = e->x();
03806 int ym = e->y();
03807 revertTransforms(xm, ym);
03808
03809 DOM::NodeImpl::MouseEvent mev( e->buttons(), DOM::NodeImpl::MouseWheel );
03810 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
03811
03812 MouseEventImpl::Orientation o = MouseEventImpl::OVertical;
03813 if (e->orientation() == Qt::Horizontal)
03814 o = MouseEventImpl::OHorizontal;
03815
03816 QMouseEvent _mouse(QEvent::MouseMove, e->pos(), Qt::NoButton, e->buttons(), e->modifiers());
03817 bool swallow = dispatchMouseEvent(EventImpl::KHTML_MOUSEWHEEL_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),
03818 true,-e->delta()/40,&_mouse,true,DOM::NodeImpl::MouseWheel,o);
03819
03820 if (swallow)
03821 return;
03822
03823 d->scrollBarMoved = true;
03824 d->scrollingFromWheel = QCursor::pos();
03825 if (d->smoothScrollMode != SSMDisabled)
03826 d->shouldSmoothScroll = true;
03827 if (d->scrollingFromWheelTimerId)
03828 killTimer(d->scrollingFromWheelTimerId);
03829 d->scrollingFromWheelTimerId = startTimer(400);
03830
03831 if (m_part->parentPart()) {
03832
03833 bool h = (static_cast<QWheelEvent*>(e)->orientation() == Qt::Horizontal);
03834 bool d = (static_cast<QWheelEvent*>(e)->delta() < 0);
03835 QScrollBar* hsb = horizontalScrollBar();
03836 QScrollBar* vsb = verticalScrollBar();
03837 if ( (h && ((d && hsb->value() == hsb->maximum()) || (!d && hsb->value() == hsb->minimum()))) ||
03838 (!h && ((d && vsb->value() == vsb->maximum()) || (!d && vsb->value() == vsb->minimum()))) ) {
03839 e->accept();
03840 return;
03841 }
03842 }
03843 QScrollArea::wheelEvent( e );
03844 }
03845
03846 }
03847 #endif
03848
03849 void KHTMLView::dragEnterEvent( QDragEnterEvent* ev )
03850 {
03851
03852 QScrollArea::dragEnterEvent( ev );
03853 }
03854
03855 void KHTMLView::dropEvent( QDropEvent *ev )
03856 {
03857
03858 QScrollArea::dropEvent( ev );
03859 }
03860
03861 void KHTMLView::focusInEvent( QFocusEvent *e )
03862 {
03863 DOM::NodeImpl* fn = m_part->xmlDocImpl() ? m_part->xmlDocImpl()->focusNode() : 0;
03864 #ifndef KHTML_NO_TYPE_AHEAD_FIND
03865 if (!fn || m_part->isCaretMode())
03866 m_part->enableFindAheadActions( true );
03867 #endif
03868 if (fn && fn->renderer() && fn->renderer()->isWidget() &&
03869 (e->reason() != Qt::MouseFocusReason) &&
03870 static_cast<khtml::RenderWidget*>(fn->renderer())->widget())
03871 static_cast<khtml::RenderWidget*>(fn->renderer())->widget()->setFocus();
03872 m_part->setSelectionVisible();
03873 QScrollArea::focusInEvent( e );
03874 }
03875
03876 void KHTMLView::focusOutEvent( QFocusEvent *e )
03877 {
03878 if (m_part) {
03879 m_part->stopAutoScroll();
03880 m_part->setSelectionVisible(false);
03881 }
03882
03883 #ifndef KHTML_NO_TYPE_AHEAD_FIND
03884 if(d->typeAheadActivated)
03885 {
03886 findTimeout();
03887 }
03888 if (m_part)
03889 m_part->enableFindAheadActions( false );
03890 #endif // KHTML_NO_TYPE_AHEAD_FIND
03891
03892 if ( d->cursorIconWidget )
03893 d->cursorIconWidget->hide();
03894
03895 QScrollArea::focusOutEvent( e );
03896 }
03897
03898 void KHTMLView::scrollContentsBy( int dx, int dy )
03899 {
03900 if (!dx && !dy) return;
03901
03902 if ( !d->firstLayoutPending && !d->complete && m_part->xmlDocImpl() &&
03903 d->layoutSchedulingEnabled) {
03904
03905 khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>( m_part->xmlDocImpl()->renderer() );
03906 if (root && root->needsLayout()) {
03907 unscheduleRelayout();
03908 layout();
03909 }
03910 }
03911
03912 if ( d->shouldSmoothScroll && d->smoothScrollMode != SSMDisabled && m_part->xmlDocImpl() &&
03913 m_part->xmlDocImpl()->renderer() && (d->smoothScrollMode != SSMWhenEfficient || d->smoothScrollMissedDeadlines != sWayTooMany)) {
03914
03915 bool doSmoothScroll = (!d->staticWidget || d->smoothScrollMode == SSMEnabled);
03916
03917 int numStaticPixels = 0;
03918 QRegion r = static_cast<RenderCanvas*>(m_part->xmlDocImpl()->renderer())->staticRegion();
03919
03920
03921 if (!doSmoothScroll && d->staticWidget == KHTMLViewPrivate::SBPartial && r.rects().size() <= 10) {
03922 foreach(QRect rr, r.rects())
03923 numStaticPixels += rr.width()*rr.height();
03924 if ((numStaticPixels < sSmoothScrollMinStaticPixels) || (numStaticPixels*8 < visibleWidth()*visibleHeight()))
03925 doSmoothScroll = true;
03926 }
03927 if (doSmoothScroll) {
03928 setupSmoothScrolling(dx, dy);
03929 return;
03930 }
03931 }
03932
03933 if (!d->scrollingSelf) {
03934 d->scrollBarMoved = true;
03935 d->contentsMoving = true;
03936
03937 scheduleRepaint(0, 0, 0, 0);
03938 }
03939
03940 if (m_part->xmlDocImpl() && m_part->xmlDocImpl()->documentElement()) {
03941
03942
03943
03944 m_part->xmlDocImpl()->documentElement()->dispatchWindowEvent(EventImpl::SCROLL_EVENT, false, false);
03945 }
03946
03947 if (QApplication::isRightToLeft())
03948 dx = -dx;
03949
03950 if (!d->smoothScrolling) {
03951 d->updateContentsXY();
03952 } else {
03953 d->contentsX -= dx;
03954 d->contentsY -= dy;
03955 }
03956 if (widget()->pos() != QPoint(0,0)) {
03957 kDebug(6000) << "Static widget wasn't positioned at (0,0). This should NOT happen. Please report this event to developers.";
03958 kDebug(6000) << kBacktrace();
03959 widget()->move(0,0);
03960 }
03961
03962 QWidget *w = widget();
03963 QPoint off;
03964 if (m_kwp->isRedirected()) {
03965
03966 KHTMLView* v = m_kwp->rootViewPos( off );
03967 if (v)
03968 w = v->widget();
03969 off = viewport()->mapTo(this, off);
03970 }
03971
03972 if ( d->staticWidget ) {
03973
03974
03975
03976 if (!d->visibleWidgets.isEmpty())
03977 checkExternalWidgetsPosition();
03978
03979 if ( d->staticWidget == KHTMLViewPrivate::SBPartial
03980 && m_part->xmlDocImpl() && m_part->xmlDocImpl()->renderer() ) {
03981
03982 QRegion r = static_cast<RenderCanvas*>(m_part->xmlDocImpl()->renderer())->staticRegion();
03983 r.translate( -contentsX(), -contentsY());
03984 QVector<QRect> ar = r.rects();
03985
03986 for (int i = 0; i < ar.size() ; ++i) {
03987 widget()->update( ar[i] );
03988 }
03989 r = QRegion(QRect(0, 0, visibleWidth(), visibleHeight())) - r;
03990 ar = r.rects();
03991 for (int i = 0; i < ar.size() ; ++i) {
03992 w->scroll( dx, dy, ar[i].translated(off) );
03993 }
03994 d->scrollExternalWidgets(dx, dy);
03995 } else {
03996
03997 widget()->update();
03998 }
03999 return;
04000 }
04001
04002 if (m_kwp->isRedirected()) {
04003 const QRect rect(off.x(), off.y(), visibleWidth() * d->zoomLevel / 100, visibleHeight() * d->zoomLevel / 100);
04004 w->scroll(dx, dy, rect);
04005 if (d->zoomLevel != 100) {
04006 w->update(rect);
04007 }
04008 } else {
04009 widget()->scroll(dx, dy, widget()->rect() & viewport()->rect());
04010 }
04011
04012 d->scrollExternalWidgets(dx, dy);
04013 }
04014
04015 void KHTMLView::setupSmoothScrolling(int dx, int dy)
04016 {
04017
04018 d->dx = d->dx + dx;
04019 d->dy = d->dy + dy;
04020
04021 if (d->dx == 0 && d->dy == 0) return;
04022
04023 int steps = sSmoothScrollTime/sSmoothScrollTick;
04024
04025
04026 d->ddx = (d->dx*16)/(steps+1);
04027 d->ddy = (d->dy*16)/(steps+1);
04028
04029 if (abs(d->ddx) < 64 && abs(d->ddy) < 64) {
04030
04031 if (d->ddx > 0) d->ddx = qMax(d->ddx, 64);
04032 if (d->ddy > 0) d->ddy = qMax(d->ddy, 64);
04033 if (d->ddx < 0) d->ddx = qMin(d->ddx, -64);
04034 if (d->ddy < 0) d->ddy = qMin(d->ddy, -64);
04035
04036 steps = qMax(d->ddx ? (d->dx*16)/d->ddx : 0, d->ddy ? (d->dy*16)/d->ddy : 0);
04037 if (steps < 1) steps = 1;
04038 d->ddx = (d->dx*16)/(steps+1);
04039 d->ddy = (d->dy*16)/(steps+1);
04040 }
04041
04042
04043 d->ddx *= 2;
04044 d->ddy *= 2;
04045
04046
04047 d->dddx = (d->ddx+1)/steps;
04048 d->dddy = (d->ddy+1)/steps;
04049
04050 if (!d->smoothScrolling) {
04051 d->startScrolling();
04052 scrollTick();
04053 }
04054 d->smoothScrollStopwatch.start();
04055 }
04056
04057 void KHTMLView::scrollTick() {
04058 if (d->dx == 0 && d->dy == 0) {
04059 d->stopScrolling();
04060 return;
04061 }
04062
04063
04064 int tddx = d->ddx + d->rdx;
04065 int tddy = d->ddy + d->rdy;
04066
04067
04068 if (tddx > 0 && tddx < 16) tddx = 16;
04069 if (tddy > 0 && tddy < 16) tddy = 16;
04070 if (tddx < 0 && tddx > -16) tddx = -16;
04071 if (tddy < 0 && tddy > -16) tddy = -16;
04072
04073
04074 int ddx = tddx / 16;
04075 int ddy = tddy / 16;
04076
04077 d->rdx = tddx % 16;
04078 d->rdy = tddy % 16;
04079
04080
04081 if (abs(ddx) > abs(d->dx)) ddx = d->dx;
04082 if (abs(ddy) > abs(d->dy)) ddy = d->dy;
04083
04084
04085 if (!ddx) ddx = d->dx;
04086 if (!ddy) ddy = d->dy;
04087
04088
04089 d->dx -= ddx;
04090 d->dy -= ddy;
04091
04092 d->shouldSmoothScroll = false;
04093 scrollContentsBy(ddx, ddy);
04094
04095
04096 if (d->smoothScrollStopwatch.elapsed() < 2*sSmoothScrollTick) {
04097
04098 int dddx = d->dddx;
04099 int dddy = d->dddy;
04100
04101 if (abs(dddx) > abs(d->ddx)) dddx = d->ddx;
04102 if (abs(dddy) > abs(d->ddy)) dddy = d->ddy;
04103
04104 d->ddx -= dddx;
04105 d->ddy -= dddy;
04106 d->smoothScrollMissedDeadlines = 0;
04107 } else {
04108 if (d->smoothScrollMissedDeadlines != sWayTooMany &&
04109 (!m_part->xmlDocImpl() || !m_part->xmlDocImpl()->parsing())) {
04110 d->smoothScrollMissedDeadlines++;
04111 if (d->smoothScrollMissedDeadlines >= sMaxMissedDeadlines) {
04112
04113
04114 d->smoothScrollMissedDeadlines = sWayTooMany;
04115 }
04116 }
04117 }
04118 d->smoothScrollStopwatch.start();
04119 }
04120
04121
04122 void KHTMLView::addChild(QWidget * child, int x, int y)
04123 {
04124 if (!child)
04125 return;
04126
04127 if (child->parent() != widget())
04128 child->setParent( widget() );
04129
04130
04131
04132 child->move(x-contentsX(), y-contentsY());
04133 }
04134
04135 void KHTMLView::timerEvent ( QTimerEvent *e )
04136 {
04137
04138 if ( e->timerId() == d->scrollTimerId ) {
04139 if( d->scrollSuspended )
04140 return;
04141 switch (d->scrollDirection) {
04142 case KHTMLViewPrivate::ScrollDown:
04143 if (contentsY() + visibleHeight () >= contentsHeight())
04144 d->newScrollTimer(this, 0);
04145 else
04146 verticalScrollBar()->setValue( verticalScrollBar()->value() +d->scrollBy );
04147 break;
04148 case KHTMLViewPrivate::ScrollUp:
04149 if (contentsY() <= 0)
04150 d->newScrollTimer(this, 0);
04151 else
04152 verticalScrollBar()->setValue( verticalScrollBar()->value() -d->scrollBy );
04153 break;
04154 case KHTMLViewPrivate::ScrollRight:
04155 if (contentsX() + visibleWidth () >= contentsWidth())
04156 d->newScrollTimer(this, 0);
04157 else
04158 horizontalScrollBar()->setValue( horizontalScrollBar()->value() +d->scrollBy );
04159 break;
04160 case KHTMLViewPrivate::ScrollLeft:
04161 if (contentsX() <= 0)
04162 d->newScrollTimer(this, 0);
04163 else
04164 horizontalScrollBar()->setValue( horizontalScrollBar()->value() -d->scrollBy );
04165 break;
04166 }
04167 return;
04168 }
04169 else if ( e->timerId() == d->scrollingFromWheelTimerId ) {
04170 killTimer( d->scrollingFromWheelTimerId );
04171 d->scrollingFromWheelTimerId = 0;
04172 } else if ( e->timerId() == d->layoutTimerId ) {
04173 if (d->firstLayoutPending && d->layoutAttemptCounter < 4
04174 && (!m_part->xmlDocImpl() || !m_part->xmlDocImpl()->readyForLayout())) {
04175 d->layoutAttemptCounter++;
04176 killTimer(d->layoutTimerId);
04177 d->layoutTimerId = 0;
04178 scheduleRelayout();
04179 return;
04180 }
04181 layout();
04182 d->scheduledLayoutCounter++;
04183 if (d->firstLayoutPending) {
04184 d->firstLayoutPending = false;
04185 verticalScrollBar()->setEnabled( true );
04186 horizontalScrollBar()->setEnabled( true );
04187 }
04188 }
04189
04190 d->contentsMoving = false;
04191 if( m_part->xmlDocImpl() ) {
04192 DOM::DocumentImpl *document = m_part->xmlDocImpl();
04193 khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer());
04194
04195 if ( root && root->needsLayout() ) {
04196 if (d->repaintTimerId)
04197 killTimer(d->repaintTimerId);
04198 d->repaintTimerId = 0;
04199 scheduleRelayout();
04200 return;
04201 }
04202 }
04203
04204 if (d->repaintTimerId)
04205 killTimer(d->repaintTimerId);
04206 d->repaintTimerId = 0;
04207
04208 QRect updateRegion;
04209 const QVector<QRect> rects = d->updateRegion.rects();
04210
04211 d->updateRegion = QRegion();
04212
04213 if ( rects.size() )
04214 updateRegion = rects[0];
04215
04216 for ( int i = 1; i < rects.size(); ++i ) {
04217 QRect newRegion = updateRegion.unite(rects[i]);
04218 if (2*newRegion.height() > 3*updateRegion.height() )
04219 {
04220 repaintContents( updateRegion );
04221 updateRegion = rects[i];
04222 }
04223 else
04224 updateRegion = newRegion;
04225 }
04226
04227 if ( !updateRegion.isNull() )
04228 repaintContents( updateRegion );
04229
04230
04231
04232
04233
04234
04235 if (d->dirtyLayout && !d->visibleWidgets.isEmpty())
04236 checkExternalWidgetsPosition();
04237
04238 d->dirtyLayout = false;
04239
04240 emit repaintAccessKeys();
04241 if (d->emitCompletedAfterRepaint) {
04242 bool full = d->emitCompletedAfterRepaint == KHTMLViewPrivate::CSFull;
04243 d->emitCompletedAfterRepaint = KHTMLViewPrivate::CSNone;
04244 if ( full )
04245 emit m_part->completed();
04246 else
04247 emit m_part->completed(true);
04248 }
04249 }
04250
04251 void KHTMLView::checkExternalWidgetsPosition()
04252 {
04253 QWidget* w;
04254 QRect visibleRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
04255 QList<RenderWidget*> toRemove;
04256 QHashIterator<void*, QWidget*> it(d->visibleWidgets);
04257 while (it.hasNext()) {
04258 int xp = 0, yp = 0;
04259 it.next();
04260 RenderWidget* rw = static_cast<RenderWidget*>( it.key() );
04261 if (!rw->absolutePosition(xp, yp) ||
04262 !visibleRect.intersects(QRect(xp, yp, it.value()->width(), it.value()->height())))
04263 toRemove.append(rw);
04264 }
04265 foreach (RenderWidget* r, toRemove)
04266 if ( (w = d->visibleWidgets.take(r) ) )
04267 w->move( 0, -500000);
04268 }
04269
04270 void KHTMLView::scheduleRelayout(khtml::RenderObject * )
04271 {
04272 if (!d->layoutSchedulingEnabled || d->layoutTimerId)
04273 return;
04274
04275 int time = 0;
04276 if (d->firstLayoutPending) {
04277
04278
04279
04280 time = d->layoutAttemptCounter ?
04281 sLayoutAttemptDelay + sLayoutAttemptIncrement*d->layoutAttemptCounter : sFirstLayoutDelay;
04282 } else if (m_part->xmlDocImpl() && m_part->xmlDocImpl()->parsing()) {
04283
04284
04285 time = qMin(2000, sParsingLayoutsInterval + d->scheduledLayoutCounter*sParsingLayoutsIncrement);
04286 }
04287 d->layoutTimerId = startTimer( time );
04288 }
04289
04290 void KHTMLView::unscheduleRelayout()
04291 {
04292 if (!d->layoutTimerId)
04293 return;
04294
04295 killTimer(d->layoutTimerId);
04296 d->layoutTimerId = 0;
04297 }
04298
04299 void KHTMLView::unscheduleRepaint()
04300 {
04301 if (!d->repaintTimerId)
04302 return;
04303
04304 killTimer(d->repaintTimerId);
04305 d->repaintTimerId = 0;
04306 }
04307
04308 void KHTMLView::scheduleRepaint(int x, int y, int w, int h, bool asap)
04309 {
04310 bool parsing = !m_part->xmlDocImpl() || m_part->xmlDocImpl()->parsing();
04311
04312
04313
04314
04315 int time = parsing && !d->firstLayoutPending ? 150 : (!asap ? ( !d->complete ? 80 : 20 ) : 0);
04316
04317 #ifdef DEBUG_FLICKER
04318 QPainter p;
04319 p.begin( viewport() );
04320
04321 int vx, vy;
04322 contentsToViewport( x, y, vx, vy );
04323 p.fillRect( vx, vy, w, h, Qt::red );
04324 p.end();
04325 #endif
04326
04327 d->updateRegion = d->updateRegion.unite(QRect(x,y,w,h));
04328
04329 if (asap && !parsing)
04330 unscheduleRepaint();
04331
04332 if ( !d->repaintTimerId )
04333 d->repaintTimerId = startTimer( time );
04334
04335
04336 }
04337
04338 void KHTMLView::complete( bool pendingAction )
04339 {
04340
04341
04342 d->complete = true;
04343
04344
04345 if (d->layoutTimerId)
04346 {
04347
04348
04349 killTimer(d->layoutTimerId);
04350 d->layoutTimerId = startTimer( 0 );
04351 d->emitCompletedAfterRepaint = pendingAction ?
04352 KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull;
04353 }
04354
04355
04356 if (d->repaintTimerId)
04357 {
04358
04359
04360 killTimer(d->repaintTimerId);
04361 d->repaintTimerId = startTimer( 0 );
04362 d->emitCompletedAfterRepaint = pendingAction ?
04363 KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull;
04364 }
04365
04366 if (!d->emitCompletedAfterRepaint)
04367 {
04368 if (!pendingAction)
04369 emit m_part->completed();
04370 else
04371 emit m_part->completed(true);
04372 }
04373
04374 }
04375
04376 void KHTMLView::updateScrollBars()
04377 {
04378 const QWidget *view = widget();
04379 if (!view)
04380 return;
04381
04382 QSize p = viewport()->size();
04383 QSize m = maximumViewportSize();
04384
04385 if (m.expandedTo(view->size()) == m)
04386 p = m;
04387
04388 QSize v = view->size();
04389 horizontalScrollBar()->setRange(0, v.width() - p.width());
04390 horizontalScrollBar()->setPageStep(p.width());
04391 verticalScrollBar()->setRange(0, v.height() - p.height());
04392 verticalScrollBar()->setPageStep(p.height());
04393 if (!d->smoothScrolling) {
04394 d->updateContentsXY();
04395 }
04396 }
04397
04398 void KHTMLView::slotMouseScrollTimer()
04399 {
04400 horizontalScrollBar()->setValue( horizontalScrollBar()->value() +d->m_mouseScroll_byX );
04401 verticalScrollBar()->setValue( verticalScrollBar()->value() +d->m_mouseScroll_byY);
04402 }
04403
04404
04405 static DOM::Position positionOfLineBoundary(const DOM::Position &pos, bool toEnd)
04406 {
04407 Selection sel = pos;
04408 sel.expandUsingGranularity(Selection::LINE);
04409 return toEnd ? sel.end() : sel.start();
04410 }
04411
04412 inline static DOM::Position positionOfLineBegin(const DOM::Position &pos)
04413 {
04414 return positionOfLineBoundary(pos, false);
04415 }
04416
04417 inline static DOM::Position positionOfLineEnd(const DOM::Position &pos)
04418 {
04419 return positionOfLineBoundary(pos, true);
04420 }
04421
04422 bool KHTMLView::caretKeyPressEvent(QKeyEvent *_ke)
04423 {
04424 EditorContext *ec = &m_part->d->editor_context;
04425 Selection &caret = ec->m_selection;
04426 Position old_pos = caret.caretPos();
04427 Position pos = old_pos;
04428 bool recalcXPos = true;
04429 bool handled = true;
04430
04431 bool ctrl = _ke->modifiers() & Qt::ControlModifier;
04432 bool shift = _ke->modifiers() & Qt::ShiftModifier;
04433
04434 switch(_ke->key()) {
04435
04436
04437 case Qt::Key_Down:
04438 pos = old_pos.nextLinePosition(caret.xPosForVerticalArrowNavigation(Selection::EXTENT));
04439 recalcXPos = false;
04440 break;
04441
04442 case Qt::Key_Up:
04443 pos = old_pos.previousLinePosition(caret.xPosForVerticalArrowNavigation(Selection::EXTENT));
04444 recalcXPos = false;
04445 break;
04446
04447 case Qt::Key_Left:
04448 pos = ctrl ? old_pos.previousWordPosition() : old_pos.previousCharacterPosition();
04449 break;
04450
04451 case Qt::Key_Right:
04452 pos = ctrl ? old_pos.nextWordPosition() : old_pos.nextCharacterPosition();
04453 break;
04454
04455 case Qt::Key_PageDown:
04456
04457 break;
04458
04459 case Qt::Key_PageUp:
04460
04461 break;
04462
04463 case Qt::Key_Home:
04464 if (ctrl)
04465 ;
04466 else
04467 pos = positionOfLineBegin(old_pos);
04468 break;
04469
04470 case Qt::Key_End:
04471 if (ctrl)
04472 ;
04473 else
04474 pos = positionOfLineEnd(old_pos);
04475 break;
04476
04477 default:
04478 handled = false;
04479
04480 }
04481
04482 if (pos != old_pos) {
04483 m_part->clearCaretRectIfNeeded();
04484
04485 caret.moveTo(shift ? caret.nonCaretPos() : pos, pos);
04486 int old_x = caret.xPosForVerticalArrowNavigation(Selection::CARETPOS);
04487
04488 m_part->selectionLayoutChanged();
04489
04490
04491 if (!recalcXPos)
04492 m_part->d->editor_context.m_xPosForVerticalArrowNavigation = old_x;
04493
04494 m_part->emitCaretPositionChanged(pos);
04495
04496 m_part->notifySelectionChanged();
04497
04498 }
04499
04500 if (handled) _ke->accept();
04501 return handled;
04502 }
04503
04504 #undef DEBUG_CARETMODE