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