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