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