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