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 #include "khtmlview.moc"
00028
00029 #include "khtmlview.h"
00030
00031 #include "khtml_part.h"
00032 #include "khtml_events.h"
00033
00034 #include "html/html_documentimpl.h"
00035 #include "html/html_inlineimpl.h"
00036 #include "html/html_formimpl.h"
00037 #include "rendering/render_arena.h"
00038 #include "rendering/render_canvas.h"
00039 #include "rendering/render_frames.h"
00040 #include "rendering/render_replaced.h"
00041 #include "rendering/render_layer.h"
00042 #include "rendering/render_line.h"
00043 #include "rendering/render_table.h"
00044
00045 #define protected public
00046 #include "rendering/render_text.h"
00047 #undef protected
00048 #include "xml/dom2_eventsimpl.h"
00049 #include "css/cssstyleselector.h"
00050 #include "misc/htmlhashes.h"
00051 #include "misc/helper.h"
00052 #include "khtml_settings.h"
00053 #include "khtml_printsettings.h"
00054
00055 #include "khtmlpart_p.h"
00056
00057 #ifndef KHTML_NO_CARET
00058 #include "khtml_caret_p.h"
00059 #include "xml/dom2_rangeimpl.h"
00060 #endif
00061
00062 #include <kapplication.h>
00063 #include <kcursor.h>
00064 #include <kdebug.h>
00065 #include <kdialogbase.h>
00066 #include <kiconloader.h>
00067 #include <kimageio.h>
00068 #include <klocale.h>
00069 #include <knotifyclient.h>
00070 #include <kprinter.h>
00071 #include <ksimpleconfig.h>
00072 #include <kstandarddirs.h>
00073 #include <kstdaccel.h>
00074 #include <kstringhandler.h>
00075 #include <kurldrag.h>
00076
00077 #include <qbitmap.h>
00078 #include <qlabel.h>
00079 #include <qobjectlist.h>
00080 #include <qpaintdevicemetrics.h>
00081 #include <qpainter.h>
00082 #include <qptrdict.h>
00083 #include <qtooltip.h>
00084 #include <qstring.h>
00085 #include <qstylesheet.h>
00086 #include <qtimer.h>
00087
00088
00089
00090
00091
00092
00093
00094 #include <X11/Xlib.h>
00095 #include <fixx11h.h>
00096
00097 #define PAINT_BUFFER_HEIGHT 128
00098
00099 #if 0
00100 namespace khtml {
00101 void dumpLineBoxes(RenderFlow *flow);
00102 }
00103 #endif
00104
00105 using namespace DOM;
00106 using namespace khtml;
00107 class KHTMLToolTip;
00108
00109
00110 #ifndef QT_NO_TOOLTIP
00111
00112 class KHTMLToolTip : public QToolTip
00113 {
00114 public:
00115 KHTMLToolTip(KHTMLView *view, KHTMLViewPrivate* vp) : QToolTip(view->viewport())
00116 {
00117 m_view = view;
00118 m_viewprivate = vp;
00119 };
00120
00121 protected:
00122 virtual void maybeTip(const QPoint &);
00123
00124 private:
00125 KHTMLView *m_view;
00126 KHTMLViewPrivate* m_viewprivate;
00127 };
00128
00129 #endif
00130
00131 class KHTMLViewPrivate {
00132 friend class KHTMLToolTip;
00133 public:
00134
00135 enum PseudoFocusNodes {
00136 PFNone,
00137 PFTop,
00138 PFBottom
00139 };
00140
00141 enum CompletedState {
00142 CSNone = 0,
00143 CSFull,
00144 CSActionPending
00145 };
00146
00147 KHTMLViewPrivate()
00148 : underMouse( 0 ), underMouseNonShared( 0 )
00149 #ifndef NO_SMOOTH_SCROLL_HACK
00150 , dx(0), dy(0), ddx(0), ddy(0), rdx(0), rdy(0), scrolling(false)
00151 #endif
00152 {
00153 #ifndef KHTML_NO_CARET
00154 m_caretViewContext = 0;
00155 m_editorContext = 0;
00156 #endif // KHTML_NO_CARET
00157 postponed_autorepeat = NULL;
00158 reset();
00159 vmode = QScrollView::Auto;
00160 hmode = QScrollView::Auto;
00161 tp=0;
00162 paintBuffer=0;
00163 vertPaintBuffer=0;
00164 formCompletions=0;
00165 prevScrollbarVisible = true;
00166 tooltip = 0;
00167 possibleTripleClick = false;
00168 emitCompletedAfterRepaint = CSNone;
00169 cursor_icon_widget = NULL;
00170 m_mouseScrollTimer = 0;
00171 m_mouseScrollIndicator = 0;
00172 }
00173 ~KHTMLViewPrivate()
00174 {
00175 delete formCompletions;
00176 delete tp; tp = 0;
00177 delete paintBuffer; paintBuffer =0;
00178 delete vertPaintBuffer;
00179 delete postponed_autorepeat;
00180 if (underMouse)
00181 underMouse->deref();
00182 if (underMouseNonShared)
00183 underMouseNonShared->deref();
00184 delete tooltip;
00185 #ifndef KHTML_NO_CARET
00186 delete m_caretViewContext;
00187 delete m_editorContext;
00188 #endif // KHTML_NO_CARET
00189 delete cursor_icon_widget;
00190 delete m_mouseScrollTimer;
00191 delete m_mouseScrollIndicator;
00192 }
00193 void reset()
00194 {
00195 if (underMouse)
00196 underMouse->deref();
00197 underMouse = 0;
00198 if (underMouseNonShared)
00199 underMouseNonShared->deref();
00200 underMouseNonShared = 0;
00201 linkPressed = false;
00202 useSlowRepaints = false;
00203 tabMovePending = false;
00204 lastTabbingDirection = true;
00205 pseudoFocusNode = PFNone;
00206 #ifndef KHTML_NO_SCROLLBARS
00207
00208
00209
00210
00211 #else
00212 vmode = QScrollView::AlwaysOff;
00213 hmode = QScrollView::AlwaysOff;
00214 #endif
00215 #ifdef DEBUG_PIXEL
00216 timer.start();
00217 pixelbooth = 0;
00218 repaintbooth = 0;
00219 #endif
00220 scrollBarMoved = false;
00221 contentsMoving = false;
00222 ignoreWheelEvents = false;
00223 borderX = 30;
00224 borderY = 30;
00225 clickX = -1;
00226 clickY = -1;
00227 prevMouseX = -1;
00228 prevMouseY = -1;
00229 clickCount = 0;
00230 isDoubleClick = false;
00231 scrollingSelf = false;
00232 delete postponed_autorepeat;
00233 postponed_autorepeat = NULL;
00234 layoutTimerId = 0;
00235 repaintTimerId = 0;
00236 scrollTimerId = 0;
00237 scrollSuspended = false;
00238 scrollSuspendPreActivate = false;
00239 complete = false;
00240 firstRelayout = true;
00241 needsFullRepaint = true;
00242 dirtyLayout = false;
00243 layoutSchedulingEnabled = true;
00244 painting = false;
00245 updateRegion = QRegion();
00246 m_dialogsAllowed = true;
00247 #ifndef KHTML_NO_CARET
00248 if (m_caretViewContext) {
00249 m_caretViewContext->caretMoved = false;
00250 m_caretViewContext->keyReleasePending = false;
00251 }
00252 #endif // KHTML_NO_CARET
00253 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00254 typeAheadActivated = false;
00255 #endif // KHTML_NO_TYPE_AHEAD_FIND
00256 accessKeysActivated = false;
00257 accessKeysPreActivate = false;
00258 emitCompletedAfterRepaint = CSNone;
00259 }
00260 void newScrollTimer(QWidget *view, int tid)
00261 {
00262
00263 view->killTimer(scrollTimerId);
00264 scrollTimerId = tid;
00265 scrollSuspended = false;
00266 }
00267 enum ScrollDirection { ScrollLeft, ScrollRight, ScrollUp, ScrollDown };
00268
00269 void adjustScroller(QWidget *view, ScrollDirection direction, ScrollDirection oppositedir)
00270 {
00271 static const struct { int msec, pixels; } timings [] = {
00272 {320,1}, {224,1}, {160,1}, {112,1}, {80,1}, {56,1}, {40,1},
00273 {28,1}, {20,1}, {20,2}, {20,3}, {20,4}, {20,6}, {20,8}, {0,0}
00274 };
00275 if (!scrollTimerId ||
00276 (scrollDirection != direction &&
00277 (scrollDirection != oppositedir || scrollSuspended))) {
00278 scrollTiming = 6;
00279 scrollBy = timings[scrollTiming].pixels;
00280 scrollDirection = direction;
00281 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00282 } else if (scrollDirection == direction &&
00283 timings[scrollTiming+1].msec && !scrollSuspended) {
00284 scrollBy = timings[++scrollTiming].pixels;
00285 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00286 } else if (scrollDirection == oppositedir) {
00287 if (scrollTiming) {
00288 scrollBy = timings[--scrollTiming].pixels;
00289 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00290 }
00291 }
00292 scrollSuspended = false;
00293 }
00294
00295 #ifndef KHTML_NO_CARET
00296
00299 CaretViewContext *caretViewContext() {
00300 if (!m_caretViewContext) m_caretViewContext = new CaretViewContext();
00301 return m_caretViewContext;
00302 }
00306 EditorContext *editorContext() {
00307 if (!m_editorContext) m_editorContext = new EditorContext();
00308 return m_editorContext;
00309 }
00310 #endif // KHTML_NO_CARET
00311
00312 #ifdef DEBUG_PIXEL
00313 QTime timer;
00314 unsigned int pixelbooth;
00315 unsigned int repaintbooth;
00316 #endif
00317
00318 QPainter *tp;
00319 QPixmap *paintBuffer;
00320 QPixmap *vertPaintBuffer;
00321 NodeImpl *underMouse;
00322 NodeImpl *underMouseNonShared;
00323
00324 bool tabMovePending:1;
00325 bool lastTabbingDirection:1;
00326 PseudoFocusNodes pseudoFocusNode:2;
00327 bool scrollBarMoved:1;
00328 bool contentsMoving:1;
00329
00330 QScrollView::ScrollBarMode vmode;
00331 QScrollView::ScrollBarMode hmode;
00332 bool prevScrollbarVisible:1;
00333 bool linkPressed:1;
00334 bool useSlowRepaints:1;
00335 bool ignoreWheelEvents:1;
00336
00337 int borderX, borderY;
00338 KSimpleConfig *formCompletions;
00339
00340 int clickX, clickY, clickCount;
00341 bool isDoubleClick;
00342
00343 int prevMouseX, prevMouseY;
00344 bool scrollingSelf;
00345 int layoutTimerId;
00346 QKeyEvent* postponed_autorepeat;
00347
00348 int repaintTimerId;
00349 int scrollTimerId;
00350 int scrollTiming;
00351 int scrollBy;
00352 ScrollDirection scrollDirection :2;
00353 bool scrollSuspended :1;
00354 bool scrollSuspendPreActivate :1;
00355 bool complete :1;
00356 bool firstRelayout :1;
00357 bool layoutSchedulingEnabled :1;
00358 bool needsFullRepaint :1;
00359 bool painting :1;
00360 bool possibleTripleClick :1;
00361 bool dirtyLayout :1;
00362 bool m_dialogsAllowed :1;
00363 QRegion updateRegion;
00364 KHTMLToolTip *tooltip;
00365 QPtrDict<QWidget> visibleWidgets;
00366 #ifndef KHTML_NO_CARET
00367 CaretViewContext *m_caretViewContext;
00368 EditorContext *m_editorContext;
00369 #endif // KHTML_NO_CARET
00370 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00371 QString findString;
00372 QTimer timer;
00373 bool findLinksOnly;
00374 bool typeAheadActivated;
00375 #endif // KHTML_NO_TYPE_AHEAD_FIND
00376 bool accessKeysActivated;
00377 bool accessKeysPreActivate;
00378 CompletedState emitCompletedAfterRepaint;
00379
00380 QWidget* cursor_icon_widget;
00381
00382
00383 int m_mouseScroll_byX : 4;
00384 int m_mouseScroll_byY : 4;
00385 QTimer *m_mouseScrollTimer;
00386 QWidget *m_mouseScrollIndicator;
00387 #ifndef NO_SMOOTH_SCROLL_HACK
00388 QTimer timer2;
00389 int dx;
00390 int dy;
00391
00392 int ddx;
00393 int ddy;
00394 int rdx;
00395 int rdy;
00396 bool scrolling;
00397 #endif
00398 };
00399
00400 #ifndef QT_NO_TOOLTIP
00401
00411 static bool findImageMapRect(HTMLImageElementImpl *img, const QPoint &scrollOfs,
00412 const QPoint &p, QRect &r, QString &s)
00413 {
00414 HTMLMapElementImpl* map;
00415 if (img && img->getDocument()->isHTMLDocument() &&
00416 (map = static_cast<HTMLDocumentImpl*>(img->getDocument())->getMap(img->imageMap()))) {
00417 RenderObject::NodeInfo info(true, false);
00418 RenderObject *rend = img->renderer();
00419 int ax, ay;
00420 if (!rend || !rend->absolutePosition(ax, ay))
00421 return false;
00422
00423 bool inside = map->mapMouseEvent(p.x() - ax + scrollOfs.x(),
00424 p.y() - ay + scrollOfs.y(), rend->contentWidth(),
00425 rend->contentHeight(), info);
00426 if (inside && info.URLElement()) {
00427 HTMLAreaElementImpl *area = static_cast<HTMLAreaElementImpl *>(info.URLElement());
00428 Q_ASSERT(area->id() == ID_AREA);
00429 s = area->getAttribute(ATTR_TITLE).string();
00430 QRegion reg = area->cachedRegion();
00431 if (!s.isEmpty() && !reg.isEmpty()) {
00432 r = reg.boundingRect();
00433 r.moveBy(ax, ay);
00434 return true;
00435 }
00436 }
00437 }
00438 return false;
00439 }
00440
00441 void KHTMLToolTip::maybeTip(const QPoint& p)
00442 {
00443 DOM::NodeImpl *node = m_viewprivate->underMouseNonShared;
00444 QRect region;
00445 while ( node ) {
00446 if ( node->isElementNode() ) {
00447 DOM::ElementImpl *e = static_cast<DOM::ElementImpl*>( node );
00448 QRect r;
00449 QString s;
00450 bool found = false;
00451
00452
00453 if (e->id() == ID_IMG && !e->getAttribute( ATTR_USEMAP ).isEmpty()) {
00454 found = findImageMapRect(static_cast<HTMLImageElementImpl *>(e),
00455 m_view->viewportToContents(QPoint(0, 0)), p, r, s);
00456 }
00457 if (!found) {
00458 s = e->getAttribute( ATTR_TITLE ).string();
00459 r = node->getRect();
00460 }
00461 region |= QRect( m_view->contentsToViewport( r.topLeft() ), r.size() );
00462 if ( !s.isEmpty() ) {
00463 tip( region, QStyleSheet::convertFromPlainText( s, QStyleSheetItem::WhiteSpaceNormal ) );
00464 break;
00465 }
00466 }
00467 node = node->parentNode();
00468 }
00469 }
00470 #endif
00471
00472 KHTMLView::KHTMLView( KHTMLPart *part, QWidget *parent, const char *name)
00473 : QScrollView( parent, name, WResizeNoErase | WRepaintNoErase )
00474 {
00475 m_medium = "screen";
00476
00477 m_part = part;
00478 d = new KHTMLViewPrivate;
00479 QScrollView::setVScrollBarMode(d->vmode);
00480 QScrollView::setHScrollBarMode(d->hmode);
00481 connect(kapp, SIGNAL(kdisplayPaletteChanged()), this, SLOT(slotPaletteChanged()));
00482 connect(this, SIGNAL(contentsMoving(int, int)), this, SLOT(slotScrollBarMoved()));
00483
00484
00485 enableClipper(true);
00486
00487 static_cast<KHTMLView *>(static_cast<QWidget *>(viewport()))->setWFlags(WPaintUnclipped);
00488
00489 setResizePolicy(Manual);
00490 viewport()->setMouseTracking(true);
00491 viewport()->setBackgroundMode(NoBackground);
00492
00493 KImageIO::registerFormats();
00494
00495 #ifndef QT_NO_TOOLTIP
00496 d->tooltip = new KHTMLToolTip( this, d );
00497 #endif
00498
00499 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00500 connect(&d->timer, SIGNAL(timeout()), this, SLOT(findTimeout()));
00501 #endif // KHTML_NO_TYPE_AHEAD_FIND
00502
00503 init();
00504
00505 viewport()->show();
00506 #ifndef NO_SMOOTH_SCROLL_HACK
00507 #define timer timer2
00508 connect(&d->timer, SIGNAL(timeout()), this, SLOT(scrollTick()));
00509 #undef timer
00510 #endif
00511 }
00512
00513 KHTMLView::~KHTMLView()
00514 {
00515 closeChildDialogs();
00516 if (m_part)
00517 {
00518
00519
00520 DOM::DocumentImpl *doc = m_part->xmlDocImpl();
00521 if (doc)
00522 doc->detach();
00523 }
00524 delete d; d = 0;
00525 }
00526
00527 void KHTMLView::init()
00528 {
00529 if(!d->paintBuffer) d->paintBuffer = new QPixmap(PAINT_BUFFER_HEIGHT, PAINT_BUFFER_HEIGHT);
00530 if(!d->vertPaintBuffer)
00531 d->vertPaintBuffer = new QPixmap(10, PAINT_BUFFER_HEIGHT);
00532 if(!d->tp) d->tp = new QPainter();
00533
00534 setFocusPolicy(QWidget::StrongFocus);
00535 viewport()->setFocusProxy(this);
00536
00537 _marginWidth = -1;
00538 _marginHeight = -1;
00539 _width = 0;
00540 _height = 0;
00541
00542 installEventFilter(this);
00543
00544 setAcceptDrops(true);
00545 QSize s = viewportSize(4095, 4095);
00546 resizeContents(s.width(), s.height());
00547 }
00548
00549 void KHTMLView::clear()
00550 {
00551
00552 setStaticBackground(true);
00553 #ifndef KHTML_NO_CARET
00554 if (!m_part->isCaretMode() && !m_part->isEditable()) caretOff();
00555 #endif
00556
00557 if( d->typeAheadActivated )
00558 findTimeout();
00559 if (d->accessKeysActivated)
00560 accessKeysTimeout();
00561 viewport()->unsetCursor();
00562 if ( d->cursor_icon_widget )
00563 d->cursor_icon_widget->hide();
00564 d->reset();
00565 killTimers();
00566 emit cleared();
00567
00568 QScrollView::setHScrollBarMode(d->hmode);
00569 QScrollView::setVScrollBarMode(d->vmode);
00570 verticalScrollBar()->setEnabled( false );
00571 horizontalScrollBar()->setEnabled( false );
00572 }
00573
00574 void KHTMLView::hideEvent(QHideEvent* e)
00575 {
00576 QScrollView::hideEvent(e);
00577 }
00578
00579 void KHTMLView::showEvent(QShowEvent* e)
00580 {
00581 QScrollView::showEvent(e);
00582 }
00583
00584 void KHTMLView::resizeEvent (QResizeEvent* e)
00585 {
00586 int dw = e->oldSize().width() - e->size().width();
00587 int dh = e->oldSize().height() - e->size().height();
00588
00589
00590
00591 dw = dw>0 ? kMax(0, contentsWidth()-dw) : contentsWidth();
00592 dh = dh>0 ? kMax(0, contentsHeight()-dh) : contentsHeight();
00593
00594 resizeContents(dw, dh);
00595
00596 QScrollView::resizeEvent(e);
00597
00598 if ( m_part && m_part->xmlDocImpl() )
00599 m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false );
00600 }
00601
00602 void KHTMLView::viewportResizeEvent (QResizeEvent* e)
00603 {
00604 QScrollView::viewportResizeEvent(e);
00605
00606
00607
00608
00609 if (d->layoutSchedulingEnabled)
00610 layout();
00611 #ifndef KHTML_NO_CARET
00612 else {
00613 hideCaret();
00614 recalcAndStoreCaretPos();
00615 showCaret();
00616 }
00617 #endif
00618
00619 KApplication::sendPostedEvents(viewport(), QEvent::Paint);
00620 }
00621
00622
00623 void KHTMLView::drawContents( QPainter*)
00624 {
00625 }
00626
00627 void KHTMLView::drawContents( QPainter *p, int ex, int ey, int ew, int eh )
00628 {
00629 #ifdef DEBUG_PIXEL
00630
00631 if ( d->timer.elapsed() > 5000 ) {
00632 qDebug( "drawed %d pixels in %d repaints the last %d milliseconds",
00633 d->pixelbooth, d->repaintbooth, d->timer.elapsed() );
00634 d->timer.restart();
00635 d->pixelbooth = 0;
00636 d->repaintbooth = 0;
00637 }
00638 d->pixelbooth += ew*eh;
00639 d->repaintbooth++;
00640 #endif
00641
00642
00643 if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
00644 p->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00645 return;
00646 } else if ( d->complete && static_cast<RenderCanvas*>(m_part->xmlDocImpl()->renderer())->needsLayout() ) {
00647
00648 unscheduleRelayout();
00649 layout();
00650 }
00651
00652 if (d->painting) {
00653 kdDebug( 6000 ) << "WARNING: drawContents reentered! " << endl;
00654 return;
00655 }
00656 d->painting = true;
00657
00658 QPoint pt = contentsToViewport(QPoint(ex, ey));
00659 QRegion cr = QRect(pt.x(), pt.y(), ew, eh);
00660
00661 for (QPtrDictIterator<QWidget> it(d->visibleWidgets); it.current(); ++it) {
00662 QWidget *w = it.current();
00663 RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
00664 if (strcmp(w->name(), "__khtml")) {
00665 int x, y;
00666 rw->absolutePosition(x, y);
00667 contentsToViewport(x, y, x, y);
00668 cr -= QRect(x, y, rw->width(), rw->height());
00669 }
00670 }
00671
00672 #if 0
00673
00674
00675 if (cr.isEmpty()) {
00676 d->painting = false;
00677 return;
00678 }
00679 #endif
00680
00681 #ifndef DEBUG_NO_PAINT_BUFFER
00682 p->setClipRegion(cr);
00683
00684 if (eh > PAINT_BUFFER_HEIGHT && ew <= 10) {
00685 if ( d->vertPaintBuffer->height() < visibleHeight() )
00686 d->vertPaintBuffer->resize(10, visibleHeight());
00687 d->tp->begin(d->vertPaintBuffer);
00688 d->tp->translate(-ex, -ey);
00689 d->tp->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00690 m_part->xmlDocImpl()->renderer()->layer()->paint(d->tp, QRect(ex, ey, ew, eh));
00691 d->tp->end();
00692 p->drawPixmap(ex, ey, *d->vertPaintBuffer, 0, 0, ew, eh);
00693 }
00694 else {
00695 if ( d->paintBuffer->width() < visibleWidth() )
00696 d->paintBuffer->resize(visibleWidth(),PAINT_BUFFER_HEIGHT);
00697
00698 int py=0;
00699 while (py < eh) {
00700 int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;
00701 d->tp->begin(d->paintBuffer);
00702 d->tp->translate(-ex, -ey-py);
00703 d->tp->fillRect(ex, ey+py, ew, ph, palette().active().brush(QColorGroup::Base));
00704 m_part->xmlDocImpl()->renderer()->layer()->paint(d->tp, QRect(ex, ey+py, ew, ph));
00705 d->tp->end();
00706
00707 p->drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph);
00708 py += PAINT_BUFFER_HEIGHT;
00709 }
00710 }
00711 #else // !DEBUG_NO_PAINT_BUFFER
00712 static int cnt=0;
00713 ex = contentsX(); ey = contentsY();
00714 ew = visibleWidth(); eh = visibleHeight();
00715 QRect pr(ex,ey,ew,eh);
00716 kdDebug() << "[" << ++cnt << "]" << " clip region: " << pr << endl;
00717
00718
00719 p->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00720 m_part->xmlDocImpl()->renderer()->layer()->paint(p, pr);
00721 #endif // DEBUG_NO_PAINT_BUFFER
00722
00723 #ifndef KHTML_NO_CARET
00724 if (d->m_caretViewContext && d->m_caretViewContext->visible) {
00725 QRect pos(d->m_caretViewContext->x, d->m_caretViewContext->y,
00726 d->m_caretViewContext->width, d->m_caretViewContext->height);
00727 if (pos.intersects(QRect(ex, ey, ew, eh))) {
00728 p->setRasterOp(XorROP);
00729 p->setPen(white);
00730 if (pos.width() == 1)
00731 p->drawLine(pos.topLeft(), pos.bottomRight());
00732 else {
00733 p->fillRect(pos, white);
00734 }
00735 }
00736 }
00737 #endif // KHTML_NO_CARET
00738
00739
00740
00741
00742 khtml::DrawContentsEvent event( p, ex, ey, ew, eh );
00743 QApplication::sendEvent( m_part, &event );
00744
00745 d->painting = false;
00746 }
00747
00748 void KHTMLView::setMarginWidth(int w)
00749 {
00750
00751 _marginWidth = w;
00752 }
00753
00754 void KHTMLView::setMarginHeight(int h)
00755 {
00756
00757 _marginHeight = h;
00758 }
00759
00760 void KHTMLView::layout()
00761 {
00762 if( m_part && m_part->xmlDocImpl() ) {
00763 DOM::DocumentImpl *document = m_part->xmlDocImpl();
00764
00765 khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer());
00766 if ( !root ) return;
00767
00768 d->layoutSchedulingEnabled=false;
00769
00770 if (document->isHTMLDocument()) {
00771 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
00772 if(body && body->renderer() && body->id() == ID_FRAMESET) {
00773 QScrollView::setVScrollBarMode(AlwaysOff);
00774 QScrollView::setHScrollBarMode(AlwaysOff);
00775 body->renderer()->setNeedsLayout(true);
00776
00777
00778
00779
00780 }
00781 else if (!d->tooltip)
00782 d->tooltip = new KHTMLToolTip( this, d );
00783 }
00784 d->needsFullRepaint = d->firstRelayout;
00785 if (_height != visibleHeight() || _width != visibleWidth()) {;
00786 d->needsFullRepaint = true;
00787 _height = visibleHeight();
00788 _width = visibleWidth();
00789 }
00790
00791
00792 root->layout();
00793
00794 emit finishedLayout();
00795 if (d->firstRelayout) {
00796
00797
00798 d->firstRelayout = false;
00799 verticalScrollBar()->setEnabled( true );
00800 horizontalScrollBar()->setEnabled( true );
00801 }
00802 #if 0
00803 ElementImpl *listitem = m_part->xmlDocImpl()->getElementById("__test_element__");
00804 if (listitem) kdDebug(6000) << "after layout, before repaint" << endl;
00805 if (listitem) dumpLineBoxes(static_cast<RenderFlow *>(listitem->renderer()));
00806 #endif
00807 #ifndef KHTML_NO_CARET
00808 hideCaret();
00809 if ((m_part->isCaretMode() || m_part->isEditable())
00810 && !d->complete && d->m_caretViewContext
00811 && !d->m_caretViewContext->caretMoved) {
00812 initCaret();
00813 } else {
00814 recalcAndStoreCaretPos();
00815 showCaret();
00816 }
00817 #endif
00818 if (d->accessKeysActivated) {
00819 emit hideAccessKeys();
00820 displayAccessKeys();
00821 }
00822
00823 }
00824 else
00825 _width = visibleWidth();
00826
00827 killTimer(d->layoutTimerId);
00828 d->layoutTimerId = 0;
00829 d->layoutSchedulingEnabled=true;
00830 }
00831
00832 void KHTMLView::closeChildDialogs()
00833 {
00834 QObjectList *dlgs = queryList("QDialog");
00835 for (QObject *dlg = dlgs->first(); dlg; dlg = dlgs->next())
00836 {
00837 KDialogBase* dlgbase = dynamic_cast<KDialogBase *>( dlg );
00838 if ( dlgbase ) {
00839 if ( dlgbase->testWFlags( WShowModal ) ) {
00840 kdDebug(6000) << "closeChildDialogs: closing dialog " << dlgbase << endl;
00841
00842
00843 dlgbase->cancel();
00844 }
00845 }
00846 else
00847 {
00848 kdWarning() << "closeChildDialogs: not a KDialogBase! Don't use QDialogs in KDE! " << static_cast<QWidget*>(dlg) << endl;
00849 static_cast<QWidget*>(dlg)->hide();
00850 }
00851 }
00852 delete dlgs;
00853 d->m_dialogsAllowed = false;
00854 }
00855
00856 bool KHTMLView::dialogsAllowed() {
00857 bool allowed = d->m_dialogsAllowed;
00858 KHTMLPart* p = m_part->parentPart();
00859 if (p && p->view())
00860 allowed &= p->view()->dialogsAllowed();
00861 return allowed;
00862 }
00863
00864 void KHTMLView::closeEvent( QCloseEvent* ev )
00865 {
00866 closeChildDialogs();
00867 QScrollView::closeEvent( ev );
00868 }
00869
00870
00871
00872
00874
00875 void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse )
00876 {
00877 if (!m_part->xmlDocImpl()) return;
00878 if (d->possibleTripleClick && ( _mouse->button() & MouseButtonMask ) == LeftButton)
00879 {
00880 viewportMouseDoubleClickEvent( _mouse );
00881 return;
00882 }
00883
00884 int xm, ym;
00885 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
00886
00887
00888 d->isDoubleClick = false;
00889
00890 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MousePress );
00891 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
00892
00893
00894
00895 if ( (_mouse->button() == MidButton) &&
00896 !m_part->d->m_bOpenMiddleClick && !d->m_mouseScrollTimer &&
00897 mev.url.isNull() && (mev.innerNode.elementId() != ID_INPUT) ) {
00898 QPoint point = mapFromGlobal( _mouse->globalPos() );
00899
00900 d->m_mouseScroll_byX = 0;
00901 d->m_mouseScroll_byY = 0;
00902
00903 d->m_mouseScrollTimer = new QTimer( this );
00904 connect( d->m_mouseScrollTimer, SIGNAL(timeout()), this, SLOT(slotMouseScrollTimer()) );
00905
00906 if ( !d->m_mouseScrollIndicator ) {
00907 QPixmap pixmap, icon;
00908 pixmap.resize( 48, 48 );
00909 pixmap.fill( QColor( qRgba( 127, 127, 127, 127 ) ) );
00910
00911 QPainter p( &pixmap );
00912 icon = KGlobal::iconLoader()->loadIcon( "1uparrow", KIcon::Small );
00913 p.drawPixmap( 16, 0, icon );
00914 icon = KGlobal::iconLoader()->loadIcon( "1leftarrow", KIcon::Small );
00915 p.drawPixmap( 0, 16, icon );
00916 icon = KGlobal::iconLoader()->loadIcon( "1downarrow", KIcon::Small );
00917 p.drawPixmap( 16, 32,icon );
00918 icon = KGlobal::iconLoader()->loadIcon( "1rightarrow", KIcon::Small );
00919 p.drawPixmap( 32, 16, icon );
00920 p.drawEllipse( 23, 23, 2, 2 );
00921
00922 d->m_mouseScrollIndicator = new QWidget( this, 0 );
00923 d->m_mouseScrollIndicator->setFixedSize( 48, 48 );
00924 d->m_mouseScrollIndicator->setPaletteBackgroundPixmap( pixmap );
00925 }
00926 d->m_mouseScrollIndicator->move( point.x()-24, point.y()-24 );
00927
00928 bool hasHorBar = visibleWidth() < contentsWidth();
00929 bool hasVerBar = visibleHeight() < contentsHeight();
00930
00931 KConfig *config = KGlobal::config();
00932 KConfigGroupSaver saver( config, "HTML Settings" );
00933 if ( config->readBoolEntry( "ShowMouseScrollIndicator", true ) ) {
00934 d->m_mouseScrollIndicator->show();
00935 d->m_mouseScrollIndicator->unsetCursor();
00936
00937 QBitmap mask = d->m_mouseScrollIndicator->paletteBackgroundPixmap()->createHeuristicMask( true );
00938
00939 if ( hasHorBar && !hasVerBar ) {
00940 QBitmap bm( 16, 16, true );
00941 bitBlt( &mask, 16, 0, &bm, 0, 0, -1, -1 );
00942 bitBlt( &mask, 16, 32, &bm, 0, 0, -1, -1 );
00943 d->m_mouseScrollIndicator->setCursor( KCursor::SizeHorCursor );
00944 }
00945 else if ( !hasHorBar && hasVerBar ) {
00946 QBitmap bm( 16, 16, true );
00947 bitBlt( &mask, 0, 16, &bm, 0, 0, -1, -1 );
00948 bitBlt( &mask, 32, 16, &bm, 0, 0, -1, -1 );
00949 d->m_mouseScrollIndicator->setCursor( KCursor::SizeVerCursor );
00950 }
00951 else
00952 d->m_mouseScrollIndicator->setCursor( KCursor::SizeAllCursor );
00953
00954 d->m_mouseScrollIndicator->setMask( mask );
00955 }
00956 else {
00957 if ( hasHorBar && !hasVerBar )
00958 viewport()->setCursor( KCursor::SizeHorCursor );
00959 else if ( !hasHorBar && hasVerBar )
00960 viewport()->setCursor( KCursor::SizeVerCursor );
00961 else
00962 viewport()->setCursor( KCursor::SizeAllCursor );
00963 }
00964
00965 return;
00966 }
00967 else if ( d->m_mouseScrollTimer ) {
00968 delete d->m_mouseScrollTimer;
00969 d->m_mouseScrollTimer = 0;
00970
00971 if ( d->m_mouseScrollIndicator )
00972 d->m_mouseScrollIndicator->hide();
00973 }
00974
00975 d->clickCount = 1;
00976 d->clickX = xm;
00977 d->clickY = ym;
00978
00979 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
00980 d->clickCount,_mouse,true,DOM::NodeImpl::MousePress);
00981
00982 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
00983 if (r && r->isWidget())
00984 _mouse->ignore();
00985
00986 if (!swallowEvent) {
00987 emit m_part->nodeActivated(mev.innerNode);
00988
00989 khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
00990 QApplication::sendEvent( m_part, &event );
00991
00992 }
00993 }
00994
00995 void KHTMLView::viewportMouseDoubleClickEvent( QMouseEvent *_mouse )
00996 {
00997 if(!m_part->xmlDocImpl()) return;
00998
00999 int xm, ym;
01000 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
01001
01002 kdDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym << endl;
01003
01004 d->isDoubleClick = true;
01005
01006 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseDblClick );
01007 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
01008
01009
01010
01011 if (d->clickCount > 0 &&
01012 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
01013 d->clickCount++;
01014 else {
01015 d->clickCount = 1;
01016 d->clickX = xm;
01017 d->clickY = ym;
01018 }
01019 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01020 d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick);
01021
01022 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
01023 if (r && r->isWidget())
01024 _mouse->ignore();
01025
01026 if (!swallowEvent) {
01027 khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode, d->clickCount );
01028 QApplication::sendEvent( m_part, &event );
01029 }
01030
01031 d->possibleTripleClick=true;
01032 QTimer::singleShot(QApplication::doubleClickInterval(),this,SLOT(tripleClickTimeout()));
01033 }
01034
01035 void KHTMLView::tripleClickTimeout()
01036 {
01037 d->possibleTripleClick = false;
01038 d->clickCount = 0;
01039 }
01040
01041 static inline void forwardPeripheralEvent(khtml::RenderWidget* r, QMouseEvent* me, int x, int y)
01042 {
01043 int absx = 0;
01044 int absy = 0;
01045 r->absolutePosition(absx, absy);
01046 QPoint p(x-absx, y-absy);
01047 QMouseEvent fw(me->type(), p, me->button(), me->state());
01048 QWidget* w = r->widget();
01049 if(w)
01050 static_cast<khtml::RenderWidget::EventPropagator*>(w)->sendEvent(&fw);
01051 }
01052
01053 void KHTMLView::viewportMouseMoveEvent( QMouseEvent * _mouse )
01054 {
01055 if ( d->m_mouseScrollTimer ) {
01056 QPoint point = mapFromGlobal( _mouse->globalPos() );
01057
01058 int deltaX = point.x() - d->m_mouseScrollIndicator->x() - 24;
01059 int deltaY = point.y() - d->m_mouseScrollIndicator->y() - 24;
01060
01061 (deltaX > 0) ? d->m_mouseScroll_byX = 1 : d->m_mouseScroll_byX = -1;
01062 (deltaY > 0) ? d->m_mouseScroll_byY = 1 : d->m_mouseScroll_byY = -1;
01063
01064 int adX = abs( deltaX );
01065 int adY = abs( deltaY );
01066
01067 if (adX > 100) d->m_mouseScroll_byX *= 7;
01068 else if (adX > 75) d->m_mouseScroll_byX *= 4;
01069 else if (adX > 50) d->m_mouseScroll_byX *= 2;
01070 else if (adX > 25) d->m_mouseScroll_byX *= 1;
01071 else d->m_mouseScroll_byX = 0;
01072
01073 if (adY > 100) d->m_mouseScroll_byY *= 7;
01074 else if (adY > 75) d->m_mouseScroll_byY *= 4;
01075 else if (adY > 50) d->m_mouseScroll_byY *= 2;
01076 else if (adY > 25) d->m_mouseScroll_byY *= 1;
01077 else d->m_mouseScroll_byY = 0;
01078
01079 if (d->m_mouseScroll_byX == 0 && d->m_mouseScroll_byY == 0) {
01080 d->m_mouseScrollTimer->stop();
01081 }
01082 else if (!d->m_mouseScrollTimer->isActive()) {
01083 d->m_mouseScrollTimer->changeInterval( 20 );
01084 }
01085 }
01086
01087 if(!m_part->xmlDocImpl()) return;
01088
01089 int xm, ym;
01090 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
01091
01092 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseMove );
01093
01094 m_part->xmlDocImpl()->prepareMouseEvent( _mouse->state() & Qt::MouseButtonMask , xm, ym, &mev );
01095
01096
01097
01098
01099
01100 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),false,
01101 0,_mouse,true,DOM::NodeImpl::MouseMove);
01102
01103 if (d->clickCount > 0 &&
01104 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() > QApplication::startDragDistance()) {
01105 d->clickCount = 0;
01106 }
01107
01108
01109 m_part->executeScheduledScript();
01110
01111 DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode();
01112 if (fn && fn != mev.innerNode.handle() &&
01113 fn->renderer() && fn->renderer()->isWidget()) {
01114 forwardPeripheralEvent(static_cast<khtml::RenderWidget*>(fn->renderer()), _mouse, xm, ym);
01115 }
01116
01117 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
01118 khtml::RenderStyle* style = (r && r->style()) ? r->style() : 0;
01119 QCursor c;
01120 bool mailtoCursor = false;
01121 switch ( style ? style->cursor() : CURSOR_AUTO) {
01122 case CURSOR_AUTO:
01123 if ( r && r->isText() )
01124 c = KCursor::ibeamCursor();
01125 if ( mev.url.length() && m_part->settings()->changeCursor() ) {
01126 c = m_part->urlCursor();
01127 if (mev.url.string().startsWith("mailto:") && mev.url.string().find('@')>0)
01128 mailtoCursor = true;
01129 }
01130
01131 if (r && r->isFrameSet() && !static_cast<RenderFrameSet*>(r)->noResize())
01132 c = QCursor(static_cast<RenderFrameSet*>(r)->cursorShape());
01133
01134 break;
01135 case CURSOR_CROSS:
01136 c = KCursor::crossCursor();
01137 break;
01138 case CURSOR_POINTER:
01139 c = m_part->urlCursor();
01140 if (mev.url.string().startsWith("mailto:") && mev.url.string().find('@')>0)
01141 mailtoCursor = true;
01142 break;
01143 case CURSOR_PROGRESS:
01144 c = KCursor::workingCursor();
01145 break;
01146 case CURSOR_MOVE:
01147 c = KCursor::sizeAllCursor();
01148 break;
01149 case CURSOR_E_RESIZE:
01150 case CURSOR_W_RESIZE:
01151 c = KCursor::sizeHorCursor();
01152 break;
01153 case CURSOR_N_RESIZE:
01154 case CURSOR_S_RESIZE:
01155 c = KCursor::sizeVerCursor();
01156 break;
01157 case CURSOR_NE_RESIZE:
01158 case CURSOR_SW_RESIZE:
01159 c = KCursor::sizeBDiagCursor();
01160 break;
01161 case CURSOR_NW_RESIZE:
01162 case CURSOR_SE_RESIZE:
01163 c = KCursor::sizeFDiagCursor();
01164 break;
01165 case CURSOR_TEXT:
01166 c = KCursor::ibeamCursor();
01167 break;
01168 case CURSOR_WAIT:
01169 c = KCursor::waitCursor();
01170 break;
01171 case CURSOR_HELP:
01172 c = KCursor::whatsThisCursor();
01173 break;
01174 case CURSOR_DEFAULT:
01175 break;
01176 }
01177
01178 if ( viewport()->cursor().handle() != c.handle() ) {
01179 if( c.handle() == KCursor::arrowCursor().handle()) {
01180 for (KHTMLPart* p = m_part; p; p = p->parentPart())
01181 p->view()->viewport()->unsetCursor();
01182 }
01183 else {
01184 viewport()->setCursor( c );
01185 }
01186 }
01187
01188 if ( mailtoCursor && isVisible() && hasFocus() ) {
01189 if( !d->cursor_icon_widget ) {
01190 QPixmap icon_pixmap = KGlobal::iconLoader()->loadIcon( "mail_generic", KIcon::Small, 0, KIcon::DefaultState, 0, true );
01191 d->cursor_icon_widget = new QWidget( NULL, NULL, WX11BypassWM );
01192 XSetWindowAttributes attr;
01193 attr.save_under = True;
01194 XChangeWindowAttributes( qt_xdisplay(), d->cursor_icon_widget->winId(), CWSaveUnder, &attr );
01195 d->cursor_icon_widget->resize( icon_pixmap.width(), icon_pixmap.height());
01196 if( icon_pixmap.mask() )
01197 d->cursor_icon_widget->setMask( *icon_pixmap.mask());
01198 else
01199 d->cursor_icon_widget->clearMask();
01200 d->cursor_icon_widget->setBackgroundPixmap( icon_pixmap );
01201 d->cursor_icon_widget->erase();
01202 }
01203 QPoint c_pos = QCursor::pos();
01204 d->cursor_icon_widget->move( c_pos.x() + 15, c_pos.y() + 15 );
01205 XRaiseWindow( qt_xdisplay(), d->cursor_icon_widget->winId());
01206 QApplication::flushX();
01207 d->cursor_icon_widget->show();
01208 }
01209 else if ( d->cursor_icon_widget )
01210 d->cursor_icon_widget->hide();
01211
01212 if (r && r->isWidget()) {
01213 _mouse->ignore();
01214 }
01215
01216
01217 d->prevMouseX = xm;
01218 d->prevMouseY = ym;
01219
01220 if (!swallowEvent) {
01221 khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
01222 QApplication::sendEvent( m_part, &event );
01223 }
01224 }
01225
01226 void KHTMLView::viewportMouseReleaseEvent( QMouseEvent * _mouse )
01227 {
01228 bool swallowEvent = false;
01229 int xm, ym;
01230 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
01231 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseRelease );
01232
01233 if ( m_part->xmlDocImpl() )
01234 {
01235 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
01236
01237 swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01238 d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease);
01239
01240 if (d->clickCount > 0 &&
01241 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance()) {
01242 QMouseEvent me(d->isDoubleClick ? QEvent::MouseButtonDblClick : QEvent::MouseButtonRelease,
01243 _mouse->pos(), _mouse->button(), _mouse->state());
01244 dispatchMouseEvent(EventImpl::CLICK_EVENT, mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01245 d->clickCount, &me, true, DOM::NodeImpl::MouseRelease);
01246 }
01247
01248 DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode();
01249 if (fn && fn != mev.innerNode.handle() &&
01250 fn->renderer() && fn->renderer()->isWidget() &&
01251 _mouse->button() != MidButton) {
01252 forwardPeripheralEvent(static_cast<khtml::RenderWidget*>(fn->renderer()), _mouse, xm, ym);
01253 }
01254
01255 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
01256 if (r && r->isWidget())
01257 _mouse->ignore();
01258 }
01259
01260 if (!swallowEvent) {
01261 khtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
01262 QApplication::sendEvent( m_part, &event );
01263 }
01264 }
01265
01266
01267 bool KHTMLView::dispatchKeyEvent( QKeyEvent *_ke )
01268 {
01269 if (!m_part->xmlDocImpl())
01270 return false;
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 if( _ke == d->postponed_autorepeat )
01292 {
01293 return false;
01294 }
01295
01296 if( _ke->type() == QEvent::KeyPress )
01297 {
01298 if( !_ke->isAutoRepeat())
01299 {
01300 bool ret = dispatchKeyEventHelper( _ke, false );
01301 if( dispatchKeyEventHelper( _ke, true ))
01302 ret = true;
01303 return ret;
01304 }
01305 else
01306 {
01307 bool ret = dispatchKeyEventHelper( _ke, true );
01308 if( !ret && d->postponed_autorepeat )
01309 keyPressEvent( d->postponed_autorepeat );
01310 delete d->postponed_autorepeat;
01311 d->postponed_autorepeat = NULL;
01312 return ret;
01313 }
01314 }
01315 else
01316 {
01317
01318
01319 if ( d->postponed_autorepeat ) {
01320 delete d->postponed_autorepeat;
01321 d->postponed_autorepeat = 0;
01322 }
01323
01324 if( !_ke->isAutoRepeat()) {
01325 return dispatchKeyEventHelper( _ke, false );
01326 }
01327 else
01328 {
01329 d->postponed_autorepeat = new QKeyEvent( _ke->type(), _ke->key(), _ke->ascii(), _ke->state(),
01330 _ke->text(), _ke->isAutoRepeat(), _ke->count());
01331 if( _ke->isAccepted())
01332 d->postponed_autorepeat->accept();
01333 else
01334 d->postponed_autorepeat->ignore();
01335 return true;
01336 }
01337 }
01338 }
01339
01340
01341 bool KHTMLView::dispatchKeyEventHelper( QKeyEvent *_ke, bool keypress )
01342 {
01343 DOM::NodeImpl* keyNode = m_part->xmlDocImpl()->focusNode();
01344 if (keyNode) {
01345 return keyNode->dispatchKeyEvent(_ke, keypress);
01346 } else {
01347 return m_part->xmlDocImpl()->dispatchKeyEvent(_ke, keypress);
01348 }
01349 }
01350
01351 void KHTMLView::keyPressEvent( QKeyEvent *_ke )
01352 {
01353 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01354 if(d->typeAheadActivated)
01355 {
01356
01357 if(_ke->key() == Key_BackSpace)
01358 {
01359 d->findString = d->findString.left(d->findString.length() - 1);
01360
01361 if(!d->findString.isEmpty())
01362 {
01363 findAhead(false);
01364 }
01365 else
01366 {
01367 findTimeout();
01368 }
01369
01370 d->timer.start(3000, true);
01371 _ke->accept();
01372 return;
01373 }
01374 else if(_ke->key() == Key_Escape)
01375 {
01376 findTimeout();
01377
01378 _ke->accept();
01379 return;
01380 }
01381 else if(_ke->key() == Key_Space || !_ke->text().stripWhiteSpace().isEmpty())
01382 {
01383 d->findString += _ke->text();
01384
01385 findAhead(true);
01386
01387 d->timer.start(3000, true);
01388 _ke->accept();
01389 return;
01390 }
01391 }
01392 #endif // KHTML_NO_TYPE_AHEAD_FIND
01393
01394 #ifndef KHTML_NO_CARET
01395 if (m_part->isEditable() || m_part->isCaretMode()
01396 || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()
01397 && m_part->xmlDocImpl()->focusNode()->contentEditable())) {
01398 d->caretViewContext()->keyReleasePending = true;
01399 caretKeyPressEvent(_ke);
01400 return;
01401 }
01402 #endif // KHTML_NO_CARET
01403
01404
01405 if (_ke->key() == Key_Control && _ke->state()==0 && !d->accessKeysActivated) d->accessKeysPreActivate=true;
01406
01407 if (_ke->key() == Key_Shift && _ke->state()==0)
01408 d->scrollSuspendPreActivate=true;
01409
01410
01411
01412
01413 if (d->accessKeysActivated)
01414 {
01415 if (_ke->state()==0 || _ke->state()==ShiftButton) {
01416 if (_ke->key() != Key_Shift) accessKeysTimeout();
01417 handleAccessKey( _ke );
01418 _ke->accept();
01419 return;
01420 }
01421 accessKeysTimeout();
01422 }
01423
01424 if ( dispatchKeyEvent( _ke )) {
01425
01426 _ke->accept();
01427 return;
01428 }
01429
01430 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01431 if((_ke->key() == '\'' || _ke->key() == '/') && !d->typeAheadActivated)
01432 {
01433 if(_ke->key() == '\'')
01434 {
01435 d->findLinksOnly = true;
01436 m_part->setStatusBarText(i18n("Starting -- find links as you type"),
01437 KHTMLPart::BarDefaultText);
01438 }
01439 else if(_ke->key() == '/')
01440 {
01441 d->findLinksOnly = false;
01442 m_part->setStatusBarText(i18n("Starting -- find text as you type"),
01443 KHTMLPart::BarDefaultText);
01444 }
01445
01446 m_part->findTextBegin();
01447 d->typeAheadActivated = true;
01448 d->timer.start(3000, true);
01449 _ke->accept();
01450 return;
01451 }
01452 #endif // KHTML_NO_TYPE_AHEAD_FIND
01453
01454 int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
01455 if (_ke->state() & Qt::ShiftButton)
01456 switch(_ke->key())
01457 {
01458 case Key_Space:
01459 if ( d->vmode == QScrollView::AlwaysOff )
01460 _ke->accept();
01461 else {
01462 scrollBy( 0, -clipper()->height() - offs );
01463 if(d->scrollSuspended)
01464 d->newScrollTimer(this, 0);
01465 }
01466 break;
01467
01468 case Key_Down:
01469 case Key_J:
01470 d->adjustScroller(this, KHTMLViewPrivate::ScrollDown, KHTMLViewPrivate::ScrollUp);
01471 break;
01472
01473 case Key_Up:
01474 case Key_K:
01475 d->adjustScroller(this, KHTMLViewPrivate::ScrollUp, KHTMLViewPrivate::ScrollDown);
01476 break;
01477
01478 case Key_Left:
01479 case Key_H:
01480 d->adjustScroller(this, KHTMLViewPrivate::ScrollLeft, KHTMLViewPrivate::ScrollRight);
01481 break;
01482
01483 case Key_Right:
01484 case Key_L:
01485 d->adjustScroller(this, KHTMLViewPrivate::ScrollRight, KHTMLViewPrivate::ScrollLeft);
01486 break;
01487 }
01488 else
01489 switch ( _ke->key() )
01490 {
01491 case Key_Down:
01492 case Key_J:
01493 if ( d->vmode == QScrollView::AlwaysOff )
01494 _ke->accept();
01495 else {
01496 if (!d->scrollTimerId || d->scrollSuspended)
01497 scrollBy( 0, 10 );
01498 if (d->scrollTimerId)
01499 d->newScrollTimer(this, 0);
01500 }
01501 break;
01502
01503 case Key_Space:
01504 case Key_Next:
01505 if ( d->vmode == QScrollView::AlwaysOff )
01506 _ke->accept();
01507 else {
01508 scrollBy( 0, clipper()->height() - offs );
01509 if(d->scrollSuspended)
01510 d->newScrollTimer(this, 0);
01511 }
01512 break;
01513
01514 case Key_Up:
01515 case Key_K:
01516 if ( d->vmode == QScrollView::AlwaysOff )
01517 _ke->accept();
01518 else {
01519 if (!d->scrollTimerId || d->scrollSuspended)
01520 scrollBy( 0, -10 );
01521 if (d->scrollTimerId)
01522 d->newScrollTimer(this, 0);
01523 }
01524 break;
01525
01526 case Key_Prior:
01527 if ( d->vmode == QScrollView::AlwaysOff )
01528 _ke->accept();
01529 else {
01530 scrollBy( 0, -clipper()->height() + offs );
01531 if(d->scrollSuspended)
01532 d->newScrollTimer(this, 0);
01533 }
01534 break;
01535 case Key_Right:
01536 case Key_L:
01537 if ( d->hmode == QScrollView::AlwaysOff )
01538 _ke->accept();
01539 else {
01540 if (!d->scrollTimerId || d->scrollSuspended)
01541 scrollBy( 10, 0 );
01542 if (d->scrollTimerId)
01543 d->newScrollTimer(this, 0);
01544 }
01545 break;
01546 case Key_Left:
01547 case Key_H:
01548 if ( d->hmode == QScrollView::AlwaysOff )
01549 _ke->accept();
01550 else {
01551 if (!d->scrollTimerId || d->scrollSuspended)
01552 scrollBy( -10, 0 );
01553 if (d->scrollTimerId)
01554 d->newScrollTimer(this, 0);
01555 }
01556 break;
01557 case Key_Enter:
01558 case Key_Return:
01559
01560
01561 if (m_part->xmlDocImpl()) {
01562 NodeImpl *n = m_part->xmlDocImpl()->focusNode();
01563 if (n)
01564 n->setActive();
01565 }
01566 break;
01567 case Key_Home:
01568 if ( d->vmode == QScrollView::AlwaysOff )
01569 _ke->accept();
01570 else {
01571 setContentsPos( 0, 0 );
01572 if(d->scrollSuspended)
01573 d->newScrollTimer(this, 0);
01574 }
01575 break;
01576 case Key_End:
01577 if ( d->vmode == QScrollView::AlwaysOff )
01578 _ke->accept();
01579 else {
01580 setContentsPos( 0, contentsHeight() - visibleHeight() );
01581 if(d->scrollSuspended)
01582 d->newScrollTimer(this, 0);
01583 }
01584 break;
01585 case Key_Shift:
01586
01587 _ke->ignore();
01588 return;
01589 default:
01590 if (d->scrollTimerId)
01591 d->newScrollTimer(this, 0);
01592 _ke->ignore();
01593 return;
01594 }
01595
01596 _ke->accept();
01597 }
01598
01599 void KHTMLView::findTimeout()
01600 {
01601 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01602 d->typeAheadActivated = false;
01603 d->findString = "";
01604 m_part->setStatusBarText(i18n("Find stopped."), KHTMLPart::BarDefaultText);
01605 #endif // KHTML_NO_TYPE_AHEAD_FIND
01606 }
01607
01608 #ifndef KHTML_NO_TYPE_AHEAD_FIND
01609 void KHTMLView::findAhead(bool increase)
01610 {
01611 QString status;
01612
01613 if(d->findLinksOnly)
01614 {
01615 m_part->findText(d->findString, KHTMLPart::FindNoPopups |
01616 KHTMLPart::FindLinksOnly, this);
01617 if(m_part->findTextNext())
01618 {
01619 status = i18n("Link found: \"%1\".");
01620 }
01621 else
01622 {
01623 if(increase) KNotifyClient::beep();
01624 status = i18n("Link not found: \"%1\".");
01625 }
01626 }
01627 else
01628 {
01629 m_part->findText(d->findString, KHTMLPart::FindNoPopups, this);
01630 if(m_part->findTextNext())
01631 {
01632 status = i18n("Text found: \"%1\".");
01633 }
01634 else
01635 {
01636 if(increase) KNotifyClient::beep();
01637 status = i18n("Text not found: \"%1\".");
01638 }
01639 }
01640
01641 m_part->setStatusBarText(status.arg(d->findString.lower()),
01642 KHTMLPart::BarDefaultText);
01643 }
01644
01645 void KHTMLView::updateFindAheadTimeout()
01646 {
01647 if( d->typeAheadActivated )
01648 d->timer.start( 3000, true );
01649 }
01650
01651 #endif // KHTML_NO_TYPE_AHEAD_FIND
01652
01653 void KHTMLView::keyReleaseEvent(QKeyEvent *_ke)
01654 {
01655 if (d->m_caretViewContext && d->m_caretViewContext->keyReleasePending) {
01656
01657 d->m_caretViewContext->keyReleasePending = false;
01658 return;
01659 }
01660
01661 if (d->accessKeysPreActivate && _ke->key() != Key_Control) d->accessKeysPreActivate=false;
01662 if (_ke->key() == Key_Control && d->accessKeysPreActivate && _ke->state() == Qt::ControlButton && !(KApplication::keyboardMouseState() & Qt::ControlButton))
01663 {
01664 displayAccessKeys();
01665 m_part->setStatusBarText(i18n("Access Keys activated"),KHTMLPart::BarOverrideText);
01666 d->accessKeysActivated = true;
01667 d->accessKeysPreActivate = false;
01668 }
01669 else if (d->accessKeysActivated) accessKeysTimeout();
01670
01671 if( d->scrollSuspendPreActivate && _ke->key() != Key_Shift )
01672 d->scrollSuspendPreActivate = false;
01673 if( _ke->key() == Key_Shift && d->scrollSuspendPreActivate && _ke->state() == Qt::ShiftButton
01674 && !(KApplication::keyboardMouseState() & Qt::ShiftButton))
01675 {
01676 if (d->scrollTimerId)
01677 {
01678 d->scrollSuspended = !d->scrollSuspended;
01679 #ifndef NO_SMOOTH_SCROLL_HACK
01680 if( d->scrollSuspended )
01681 stopScrolling();
01682 #endif
01683 }
01684 }
01685
01686
01687 if ( dispatchKeyEvent( _ke ) )
01688 {
01689 _ke->accept();
01690 return;
01691 }
01692
01693 QScrollView::keyReleaseEvent(_ke);
01694 }
01695
01696 void KHTMLView::contentsContextMenuEvent ( QContextMenuEvent * )
01697 {
01698
01699 #if 0
01700 if (!m_part->xmlDocImpl()) return;
01701 int xm = _ce->x();
01702 int ym = _ce->y();
01703
01704 DOM::NodeImpl::MouseEvent mev( _ce->state(), DOM::NodeImpl::MouseMove );
01705 m_part->xmlDocImpl()->prepareMouseEvent( xm, ym, &mev );
01706
01707 NodeImpl *targetNode = mev.innerNode.handle();
01708 if (targetNode && targetNode->renderer() && targetNode->renderer()->isWidget()) {
01709 int absx = 0;
01710 int absy = 0;
01711 targetNode->renderer()->absolutePosition(absx,absy);
01712 QPoint pos(xm-absx,ym-absy);
01713
01714 QWidget *w = static_cast<RenderWidget*>(targetNode->renderer())->widget();
01715 QContextMenuEvent cme(_ce->reason(),pos,_ce->globalPos(),_ce->state());
01716 setIgnoreEvents(true);
01717 QApplication::sendEvent(w,&cme);
01718 setIgnoreEvents(false);
01719 }
01720 #endif
01721 }
01722
01723 bool KHTMLView::focusNextPrevChild( bool next )
01724 {
01725
01726 if (m_part->xmlDocImpl() && focusNextPrevNode(next))
01727 {
01728 if (m_part->xmlDocImpl()->focusNode())
01729 kdDebug() << "focusNode.name: "
01730 << m_part->xmlDocImpl()->focusNode()->nodeName().string() << endl;
01731 return true;
01732 }
01733
01734
01735 d->pseudoFocusNode = KHTMLViewPrivate::PFNone;
01736 if (m_part->parentPart() && m_part->parentPart()->view())
01737 return m_part->parentPart()->view()->focusNextPrevChild(next);
01738
01739 return QWidget::focusNextPrevChild(next);
01740 }
01741
01742 void KHTMLView::doAutoScroll()
01743 {
01744 QPoint pos = QCursor::pos();
01745 pos = viewport()->mapFromGlobal( pos );
01746
01747 int xm, ym;
01748 viewportToContents(pos.x(), pos.y(), xm, ym);
01749
01750 pos = QPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y());
01751 if ( (pos.y() < 0) || (pos.y() > visibleHeight()) ||
01752 (pos.x() < 0) || (pos.x() > visibleWidth()) )
01753 {
01754 ensureVisible( xm, ym, 0, 5 );
01755
01756 #ifndef KHTML_NO_SELECTION
01757
01758 DOM::Node innerNode;
01759 if (m_part->isExtendingSelection()) {
01760 RenderObject::NodeInfo renderInfo(true, false);
01761 m_part->xmlDocImpl()->renderer()->layer()
01762 ->nodeAtPoint(renderInfo, xm, ym);
01763 innerNode = renderInfo.innerNode();
01764 }
01765
01766 if (innerNode.handle() && innerNode.handle()->renderer()) {
01767 int absX, absY;
01768 innerNode.handle()->renderer()->absolutePosition(absX, absY);
01769
01770 m_part->extendSelectionTo(xm, ym, absX, absY, innerNode);
01771 }
01772 #endif // KHTML_NO_SELECTION
01773 }
01774 }
01775
01776
01777 class HackWidget : public QWidget
01778 {
01779 public:
01780 inline void setNoErase() { setWFlags(getWFlags()|WRepaintNoErase); }
01781 };
01782
01783 bool KHTMLView::eventFilter(QObject *o, QEvent *e)
01784 {
01785 if ( e->type() == QEvent::AccelOverride ) {
01786 QKeyEvent* ke = (QKeyEvent*) e;
01787
01788 if (m_part->isEditable() || m_part->isCaretMode()
01789 || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()
01790 && m_part->xmlDocImpl()->focusNode()->contentEditable())) {
01791
01792 if ( (ke->state() & ControlButton) || (ke->state() & ShiftButton) ) {
01793 switch ( ke->key() ) {
01794 case Key_Left:
01795 case Key_Right:
01796 case Key_Up:
01797 case Key_Down:
01798 case Key_Home:
01799 case Key_End:
01800 ke->accept();
01801
01802 return true;
01803 default:
01804 break;
01805 }
01806 }
01807 }
01808 }
01809
01810 if ( e->type() == QEvent::Leave && d->cursor_icon_widget )
01811 d->cursor_icon_widget->hide();
01812
01813 QWidget *view = viewport();
01814
01815 if (o == view) {
01816
01817
01818 if(e->type() == QEvent::ChildInserted) {
01819 QObject *c = static_cast<QChildEvent *>(e)->child();
01820 if (c->isWidgetType()) {
01821 QWidget *w = static_cast<QWidget *>(c);
01822
01823 if (w->parentWidget(true) == view) {
01824 if (!strcmp(w->name(), "__khtml")) {
01825 w->installEventFilter(this);
01826 w->unsetCursor();
01827 if (!::qt_cast<QFrame*>(w))
01828 w->setBackgroundMode( QWidget::NoBackground );
01829 static_cast<HackWidget *>(w)->setNoErase();
01830 if (w->children()) {
01831 QObjectListIterator it(*w->children());
01832 for (; it.current(); ++it) {
01833 QWidget *widget = ::qt_cast<QWidget *>(it.current());
01834 if (widget && !widget->isTopLevel()) {
01835 if (!::qt_cast<QFrame*>(w))
01836 widget->setBackgroundMode( QWidget::NoBackground );
01837 static_cast<HackWidget *>(widget)->setNoErase();
01838 widget->installEventFilter(this);
01839 }
01840 }
01841 }
01842 }
01843 }
01844 }
01845 }
01846 } else if (o->isWidgetType()) {
01847 QWidget *v = static_cast<QWidget *>(o);
01848 QWidget *c = v;
01849 while (v && v != view) {
01850 c = v;
01851 v = v->parentWidget(true);
01852 }
01853
01854 if (v && !strcmp(c->name(), "__khtml")) {
01855 bool block = false;
01856 QWidget *w = static_cast<QWidget *>(o);
01857 switch(e->type()) {
01858 case QEvent::Paint:
01859 if (!allowWidgetPaintEvents) {
01860
01861
01862 block = true;
01863 int x = 0, y = 0;
01864 QWidget *v = w;
01865 while (v && v != view) {
01866 x += v->x();
01867 y += v->y();
01868 v = v->parentWidget();
01869 }
01870 viewportToContents( x, y, x, y );
01871 QPaintEvent *pe = static_cast<QPaintEvent *>(e);
01872 bool asap = !d->contentsMoving && ::qt_cast<QScrollView *>(c);
01873
01874
01875 if ( asap && !d->painting && m_part->xmlDocImpl() && m_part->xmlDocImpl()->renderer() &&
01876 !static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer())->needsLayout() ) {
01877 repaintContents(x + pe->rect().x(), y + pe->rect().y(),
01878 pe->rect().width(), pe->rect().height(), true);
01879 } else {
01880 scheduleRepaint(x + pe->rect().x(), y + pe->rect().y(),
01881 pe->rect().width(), pe->rect().height(), asap);
01882 }
01883 }
01884 break;
01885 case QEvent::MouseMove:
01886 case QEvent::MouseButtonPress:
01887 case QEvent::MouseButtonRelease:
01888 case QEvent::MouseButtonDblClick: {
01889 if (w->parentWidget() == view && !::qt_cast<QScrollBar *>(w)) {
01890 QMouseEvent *me = static_cast<QMouseEvent *>(e);
01891 QPoint pt = (me->pos() + w->pos());
01892 QMouseEvent me2(me->type(), pt, me->button(), me->state());
01893
01894 if (e->type() == QEvent::MouseMove)
01895 viewportMouseMoveEvent(&me2);
01896 else if(e->type() == QEvent::MouseButtonPress)
01897 viewportMousePressEvent(&me2);
01898 else if(e->type() == QEvent::MouseButtonRelease)
01899 viewportMouseReleaseEvent(&me2);
01900 else
01901 viewportMouseDoubleClickEvent(&me2);
01902 block = true;
01903 }
01904 break;
01905 }
01906 case QEvent::KeyPress:
01907 case QEvent::KeyRelease:
01908 if (w->parentWidget() == view && !::qt_cast<QScrollBar *>(w)) {
01909 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
01910 if (e->type() == QEvent::KeyPress)
01911 keyPressEvent(ke);
01912 else
01913 keyReleaseEvent(ke);
01914 block = true;
01915 }
01916 default:
01917 break;
01918 }
01919 if (block) {
01920
01921 return true;
01922 }
01923 }
01924 }
01925
01926
01927 return QScrollView::eventFilter(o, e);
01928 }
01929
01930
01931 DOM::NodeImpl *KHTMLView::nodeUnderMouse() const
01932 {
01933 return d->underMouse;
01934 }
01935
01936 DOM::NodeImpl *KHTMLView::nonSharedNodeUnderMouse() const
01937 {
01938 return d->underMouseNonShared;
01939 }
01940
01941 bool KHTMLView::scrollTo(const QRect &bounds)
01942 {
01943 d->scrollingSelf = true;
01944
01945 int x, y, xe, ye;
01946 x = bounds.left();
01947 y = bounds.top();
01948 xe = bounds.right();
01949 ye = bounds.bottom();
01950
01951
01952
01953 int deltax;
01954 int deltay;
01955
01956 int curHeight = visibleHeight();
01957 int curWidth = visibleWidth();
01958
01959 if (ye-y>curHeight-d->borderY)
01960 ye = y + curHeight - d->borderY;
01961
01962 if (xe-x>curWidth-d->borderX)
01963 xe = x + curWidth - d->borderX;
01964
01965
01966 if (x < contentsX() + d->borderX )
01967 deltax = x - contentsX() - d->borderX;
01968
01969 else if (xe + d->borderX > contentsX() + curWidth)
01970 deltax = xe + d->borderX - ( contentsX() + curWidth );
01971 else
01972 deltax = 0;
01973
01974
01975 if (y < contentsY() + d->borderY)
01976 deltay = y - contentsY() - d->borderY;
01977
01978 else if (ye + d->borderY > contentsY() + curHeight)
01979 deltay = ye + d->borderY - ( contentsY() + curHeight );
01980 else
01981 deltay = 0;
01982
01983 int maxx = curWidth-d->borderX;
01984 int maxy = curHeight-d->borderY;
01985
01986 int scrollX,scrollY;
01987
01988 scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax>-maxx ? deltax : -maxx);
01989 scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay>-maxy ? deltay : -maxy);
01990
01991 if (contentsX() + scrollX < 0)
01992 scrollX = -contentsX();
01993 else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
01994 scrollX = contentsWidth() - visibleWidth() - contentsX();
01995
01996 if (contentsY() + scrollY < 0)
01997 scrollY = -contentsY();
01998 else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
01999 scrollY = contentsHeight() - visibleHeight() - contentsY();
02000
02001 scrollBy(scrollX, scrollY);
02002
02003 d->scrollingSelf = false;
02004
02005 if ( (abs(deltax)<=maxx) && (abs(deltay)<=maxy) )
02006 return true;
02007 else return false;
02008
02009 }
02010
02011 bool KHTMLView::focusNextPrevNode(bool next)
02012 {
02013
02014
02015
02016
02017
02018
02019
02020 DocumentImpl *doc = m_part->xmlDocImpl();
02021 NodeImpl *oldFocusNode = doc->focusNode();
02022
02023 #if 1
02024
02025
02026
02027 if (d->scrollBarMoved)
02028 {
02029 NodeImpl *toFocus;
02030 if (next)
02031 toFocus = doc->nextFocusNode(oldFocusNode);
02032 else
02033 toFocus = doc->previousFocusNode(oldFocusNode);
02034
02035 if (!toFocus && oldFocusNode)
02036 if (next)
02037 toFocus = doc->nextFocusNode(NULL);
02038 else
02039 toFocus = doc->previousFocusNode(NULL);
02040
02041 while (toFocus && toFocus != oldFocusNode)
02042 {
02043
02044 QRect focusNodeRect = toFocus->getRect();
02045 if ((focusNodeRect.left() > contentsX()) && (focusNodeRect.right() < contentsX() + visibleWidth()) &&
02046 (focusNodeRect.top() > contentsY()) && (focusNodeRect.bottom() < contentsY() + visibleHeight())) {
02047 {
02048 QRect r = toFocus->getRect();
02049 ensureVisible( r.right(), r.bottom());
02050 ensureVisible( r.left(), r.top());
02051 d->scrollBarMoved = false;
02052 d->tabMovePending = false;
02053 d->lastTabbingDirection = next;
02054 d->pseudoFocusNode = KHTMLViewPrivate::PFNone;
02055 m_part->xmlDocImpl()->setFocusNode(toFocus);
02056 Node guard(toFocus);
02057 if (!toFocus->hasOneRef() )
02058 {
02059 emit m_part->nodeActivated(Node(toFocus));
02060 }
02061 return true;
02062 }
02063 }
02064 if (next)
02065 toFocus = doc->nextFocusNode(toFocus);
02066 else
02067 toFocus = doc->previousFocusNode(toFocus);
02068
02069 if (!toFocus && oldFocusNode)
02070 if (next)
02071 toFocus = doc->nextFocusNode(NULL);
02072 else
02073 toFocus = doc->previousFocusNode(NULL);
02074 }
02075
02076 d->scrollBarMoved = false;
02077 }
02078 #endif
02079
02080 if (!oldFocusNode && d->pseudoFocusNode == KHTMLViewPrivate::PFNone)
02081 {
02082 ensureVisible(contentsX(), next?0:contentsHeight());
02083 d->scrollBarMoved = false;
02084 d->pseudoFocusNode = next?KHTMLViewPrivate::PFTop:KHTMLViewPrivate::PFBottom;
02085 return true;
02086 }
02087
02088 NodeImpl *newFocusNode = NULL;
02089
02090 if (d->tabMovePending && next != d->lastTabbingDirection)
02091 {
02092
02093 newFocusNode = oldFocusNode;
02094 }
02095 else if (next)
02096 {
02097 if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFTop )
02098 newFocusNode = doc->nextFocusNode(oldFocusNode);
02099 }
02100 else
02101 {
02102 if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFBottom )
02103 newFocusNode = doc->previousFocusNode(oldFocusNode);
02104 }
02105
02106 bool targetVisible = false;
02107 if (!newFocusNode)
02108 {
02109 if ( next )
02110 {
02111 targetVisible = scrollTo(QRect(contentsX()+visibleWidth()/2,contentsHeight()-d->borderY,0,0));
02112 }
02113 else
02114 {
02115 targetVisible = scrollTo(QRect(contentsX()+visibleWidth()/2,d->borderY,0,0));
02116 }
02117 }
02118 else
02119 {
02120 #ifndef KHTML_NO_CARET
02121
02122 if (!m_part->isCaretMode() && !m_part->isEditable()
02123 && newFocusNode->contentEditable()) {
02124 d->caretViewContext();
02125 moveCaretTo(newFocusNode, 0L, true);
02126 } else {
02127 caretOff();
02128 }
02129 #endif // KHTML_NO_CARET
02130
02131 targetVisible = scrollTo(newFocusNode->getRect());
02132 }
02133
02134 if (targetVisible)
02135 {
02136
02137 d->tabMovePending = false;
02138
02139 m_part->xmlDocImpl()->setFocusNode(newFocusNode);
02140 if (newFocusNode)
02141 {
02142 Node guard(newFocusNode);
02143 if (!newFocusNode->hasOneRef() )
02144 {
02145 emit m_part->nodeActivated(Node(newFocusNode));
02146 }
02147 return true;
02148 }
02149 else
02150 {
02151 d->pseudoFocusNode = next?KHTMLViewPrivate::PFBottom:KHTMLViewPrivate::PFTop;
02152 return false;
02153 }
02154 }
02155 else
02156 {
02157 if (!d->tabMovePending)
02158 d->lastTabbingDirection = next;
02159 d->tabMovePending = true;
02160 return true;
02161 }
02162 }
02163
02164 void KHTMLView::displayAccessKeys()
02165 {
02166 for( NodeImpl* n = m_part->xmlDocImpl(); n != NULL; n = n->traverseNextNode()) {
02167 if( n->isElementNode()) {
02168 ElementImpl* en = static_cast< ElementImpl* >( n );
02169 DOMString s = en->getAttribute( ATTR_ACCESSKEY );
02170 if( s.length() == 1) {
02171 QRect rec=en->getRect();
02172 QLabel *lab=new QLabel(s.string(),viewport(),0,Qt::WDestructiveClose);
02173 connect( this, SIGNAL(hideAccessKeys()), lab, SLOT(close()) );
02174 connect( this, SIGNAL(repaintAccessKeys()), lab, SLOT(repaint()));
02175 lab->setPalette(QToolTip::palette());
02176 lab->setLineWidth(2);
02177 lab->setFrameStyle(QFrame::Box | QFrame::Plain);
02178 lab->setMargin(3);
02179 lab->adjustSize();
02180 addChild(lab,
02181 KMIN(rec.left()+rec.width()/2, contentsWidth() - lab->width()),
02182 KMIN(rec.top()+rec.height()/2, contentsHeight() - lab->height()));
02183 showChild(lab);
02184 }
02185 }
02186 }
02187 }
02188
02189 void KHTMLView::accessKeysTimeout()
02190 {
02191 d->accessKeysActivated=false;
02192 d->accessKeysPreActivate = false;
02193 m_part->setStatusBarText(QString::null, KHTMLPart::BarOverrideText);
02194 emit hideAccessKeys();
02195 }
02196
02197
02198 bool KHTMLView::handleAccessKey( const QKeyEvent* ev )
02199 {
02200
02201
02202 QChar c;
02203 if( ev->key() >= Key_A && ev->key() <= Key_Z )
02204 c = 'A' + ev->key() - Key_A;
02205 else if( ev->key() >= Key_0 && ev->key() <= Key_9 )
02206 c = '0' + ev->key() - Key_0;
02207 else {
02208
02209
02210 if( ev->text().length() == 1 )
02211 c = ev->text()[ 0 ];
02212 }
02213 if( c.isNull())
02214 return false;
02215 return focusNodeWithAccessKey( c );
02216 }
02217
02218 bool KHTMLView::focusNodeWithAccessKey( QChar c, KHTMLView* caller )
02219 {
02220 DocumentImpl *doc = m_part->xmlDocImpl();
02221 if( !doc )
02222 return false;
02223 ElementImpl* node = doc->findAccessKeyElement( c );
02224 if( !node ) {
02225 QPtrList<KParts::ReadOnlyPart> frames = m_part->frames();
02226 for( QPtrListIterator<KParts::ReadOnlyPart> it( frames );
02227 it != NULL;
02228 ++it ) {
02229 if( !(*it)->inherits( "KHTMLPart" ))
02230 continue;
02231 KHTMLPart* part = static_cast< KHTMLPart* >( *it );
02232 if( part->view() && part->view() != caller
02233 && part->view()->focusNodeWithAccessKey( c, this ))
02234 return true;
02235 }
02236
02237 if (m_part->parentPart() && m_part->parentPart()->view()
02238 && m_part->parentPart()->view() != caller )
02239 return m_part->parentPart()->view()->focusNodeWithAccessKey( c, this );
02240 return false;
02241 }
02242
02243
02244 #ifndef KHTML_NO_CARET
02245
02246 if (!m_part->isCaretMode() && !m_part->isEditable()
02247 && node->contentEditable()) {
02248 d->caretViewContext();
02249 moveCaretTo(node, 0L, true);
02250 } else {
02251 caretOff();
02252 }
02253 #endif // KHTML_NO_CARET
02254
02255 QRect r = node->getRect();
02256 ensureVisible( r.right(), r.bottom());
02257 ensureVisible( r.left(), r.top());
02258
02259 Node guard( node );
02260 if( node->isFocusable()) {
02261 if (node->id()==ID_LABEL) {
02262
02263 node=static_cast<ElementImpl *>(static_cast< HTMLLabelElementImpl* >( node )->getFormElement());
02264 if (!node) return true;
02265 guard = node;
02266 }
02267
02268 QFocusEvent::setReason( QFocusEvent::Shortcut );
02269 m_part->xmlDocImpl()->setFocusNode(node);
02270 QFocusEvent::resetReason();
02271 if( node != NULL && node->hasOneRef())
02272 return true;
02273 emit m_part->nodeActivated(Node(node));
02274 if( node != NULL && node->hasOneRef())
02275 return true;
02276 }
02277
02278 switch( node->id()) {
02279 case ID_A:
02280 static_cast< HTMLAnchorElementImpl* >( node )->click();
02281 break;
02282 case ID_INPUT:
02283 static_cast< HTMLInputElementImpl* >( node )->click();
02284 break;
02285 case ID_BUTTON:
02286 static_cast< HTMLButtonElementImpl* >( node )->click();
02287 break;
02288 case ID_AREA:
02289 static_cast< HTMLAreaElementImpl* >( node )->click();
02290 break;
02291 case ID_TEXTAREA:
02292 break;
02293 case ID_LEGEND:
02294
02295 break;
02296 }
02297 return true;
02298 }
02299
02300 void KHTMLView::setMediaType( const QString &medium )
02301 {
02302 m_medium = medium;
02303 }
02304
02305 QString KHTMLView::mediaType() const
02306 {
02307 return m_medium;
02308 }
02309
02310 void KHTMLView::setWidgetVisible(RenderWidget* w, bool vis)
02311 {
02312 if (vis) {
02313 d->visibleWidgets.replace(w, w->widget());
02314 }
02315 else
02316 d->visibleWidgets.remove(w);
02317 }
02318
02319 bool KHTMLView::needsFullRepaint() const
02320 {
02321 return d->needsFullRepaint;
02322 }
02323
02324 void KHTMLView::print()
02325 {
02326 print( false );
02327 }
02328
02329 void KHTMLView::print(bool quick)
02330 {
02331 if(!m_part->xmlDocImpl()) return;
02332 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
02333 if(!root) return;
02334
02335
02336 KPrinter *printer = new KPrinter(true, QPrinter::PrinterResolution);
02337 printer->addDialogPage(new KHTMLPrintSettings());
02338 QString docname = m_part->xmlDocImpl()->URL().prettyURL();
02339 if ( !docname.isEmpty() )
02340 docname = KStringHandler::csqueeze(docname, 80);
02341 if(quick || printer->setup(this, i18n("Print %1").arg(docname))) {
02342 viewport()->setCursor( waitCursor );
02343
02344 printer->setFullPage(false);
02345 printer->setCreator(QString("KDE %1.%2.%3 HTML Library").arg(KDE_VERSION_MAJOR).arg(KDE_VERSION_MINOR).arg(KDE_VERSION_RELEASE));
02346 printer->setDocName(docname);
02347
02348 QPainter *p = new QPainter;
02349 p->begin( printer );
02350 khtml::setPrintPainter( p );
02351
02352 m_part->xmlDocImpl()->setPaintDevice( printer );
02353 QString oldMediaType = mediaType();
02354 setMediaType( "print" );
02355
02356
02357
02358 m_part->xmlDocImpl()->setPrintStyleSheet( printer->option("app-khtml-printfriendly") == "true" ?
02359 "* { background-image: none !important;"
02360 " background-color: white !important;"
02361 " color: black !important; }"
02362 "body { margin: 0px !important; }"
02363 "html { margin: 0px !important; }" :
02364 "body { margin: 0px !important; }"
02365 "html { margin: 0px !important; }"
02366 );
02367
02368 QPaintDeviceMetrics metrics( printer );
02369
02370
02371
02372
02373
02374
02375 kdDebug(6000) << "printing: physical page width = " << metrics.width()
02376 << " height = " << metrics.height() << endl;
02377 root->setPrintingMode(true);
02378 root->setWidth(metrics.width());
02379
02380 m_part->xmlDocImpl()->styleSelector()->computeFontSizes(&metrics, 100);
02381 m_part->xmlDocImpl()->updateStyleSelector();
02382 root->setPrintImages( printer->option("app-khtml-printimages") == "true");
02383 root->setNeedsLayoutAndMinMaxRecalc();
02384 root->layout();
02385 khtml::RenderWidget::flushWidgetResizes();
02386
02387 bool printHeader = (printer->option("app-khtml-printheader") == "true");
02388
02389 int headerHeight = 0;
02390 QFont headerFont("helvetica", 8);
02391
02392 QString headerLeft = KGlobal::locale()->formatDate(QDate::currentDate(),true);
02393 QString headerMid = docname;
02394 QString headerRight;
02395
02396 if (printHeader)
02397 {
02398 p->setFont(headerFont);
02399 headerHeight = (p->fontMetrics().lineSpacing() * 3) / 2;
02400 }
02401
02402
02403 kdDebug(6000) << "printing: html page width = " << root->docWidth()
02404 << " height = " << root->docHeight() << endl;
02405 kdDebug(6000) << "printing: margins left = " << printer->margins().width()
02406 << " top = " << printer->margins().height() << endl;
02407 kdDebug(6000) << "printing: paper width = " << metrics.width()
02408 << " height = " << metrics.height() << endl;
02409
02410
02411 int pageHeight = metrics.height();
02412 int pageWidth = metrics.width();
02413 p->setClipRect(0,0, pageWidth, pageHeight);
02414
02415 pageHeight -= headerHeight;
02416
02417 bool scalePage = false;
02418 double scale = 0.0;
02419 #ifndef QT_NO_TRANSFORMATIONS
02420 if(root->docWidth() > metrics.width()) {
02421 scalePage = true;
02422 scale = ((double) metrics.width())/((double) root->docWidth());
02423 pageHeight = (int) (pageHeight/scale);
02424 pageWidth = (int) (pageWidth/scale);
02425 headerHeight = (int) (headerHeight/scale);
02426 }
02427 #endif
02428 kdDebug(6000) << "printing: scaled html width = " << pageWidth
02429 << " height = " << pageHeight << endl;
02430
02431
02432 if (printHeader)
02433 {
02434 int available_width = metrics.width() - 10 -
02435 2 * kMax(p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerLeft).width(),
02436 p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerRight).width());
02437 if (available_width < 150)
02438 available_width = 150;
02439 int mid_width;
02440 int squeeze = 120;
02441 do {
02442 headerMid = KStringHandler::csqueeze(docname, squeeze);
02443 mid_width = p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerMid).width();
02444 squeeze -= 10;
02445 } while (mid_width > available_width);
02446 }
02447
02448 int top = 0;
02449 int page = 1;
02450 int bottom = 0;
02451 int oldbottom = 0;
02452 while(top < root->docHeight()) {
02453 if(top > 0) printer->newPage();
02454 if (printHeader)
02455 {
02456 int dy = p->fontMetrics().lineSpacing();
02457 p->setPen(Qt::black);
02458 p->setFont(headerFont);
02459
02460 headerRight = QString("#%1").arg(page);
02461
02462 p->drawText(0, 0, metrics.width(), dy, Qt::AlignLeft, headerLeft);
02463 p->drawText(0, 0, metrics.width(), dy, Qt::AlignHCenter, headerMid);
02464 p->drawText(0, 0, metrics.width(), dy, Qt::AlignRight, headerRight);
02465 }
02466
02467 #ifndef QT_NO_TRANSFORMATIONS
02468 if (scalePage)
02469 p->scale(scale, scale);
02470 #endif
02471 p->translate(0, headerHeight-top);
02472
02473 oldbottom = top+pageHeight;
02474 root->setTruncatedAt(oldbottom);
02475
02476 root->layer()->paint(p, QRect(0, top, pageWidth, pageHeight));
02477 bottom = root->bestTruncatedAt();
02478 kdDebug(6000) << "printed: page " << page <<" truncatedAt = " << oldbottom
02479 << " bestTruncatedAt = " << bottom << endl;
02480 if (bottom == 0) bottom = oldbottom;
02481
02482 if (bottom >= root->docHeight())
02483 break;
02484
02485 top = bottom;
02486 p->resetXForm();
02487 page++;
02488 }
02489
02490 p->end();
02491 delete p;
02492
02493
02494 root->setPrintingMode(false);
02495 khtml::setPrintPainter( 0 );
02496 setMediaType( oldMediaType );
02497 m_part->xmlDocImpl()->setPaintDevice( this );
02498 m_part->xmlDocImpl()->styleSelector()->computeFontSizes(m_part->xmlDocImpl()->paintDeviceMetrics(), m_part->zoomFactor());
02499 m_part->xmlDocImpl()->updateStyleSelector();
02500 viewport()->unsetCursor();
02501 }
02502 delete printer;
02503 }
02504
02505 void KHTMLView::slotPaletteChanged()
02506 {
02507 if(!m_part->xmlDocImpl()) return;
02508 DOM::DocumentImpl *document = m_part->xmlDocImpl();
02509 if (!document->isHTMLDocument()) return;
02510 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(document->renderer());
02511 if(!root) return;
02512 root->style()->resetPalette();
02513 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
02514 if(!body) return;
02515 body->setChanged(true);
02516 body->recalcStyle( NodeImpl::Force );
02517 }
02518
02519 void KHTMLView::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
02520 {
02521 if(!m_part->xmlDocImpl()) return;
02522 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
02523 if(!root) return;
02524
02525 m_part->xmlDocImpl()->setPaintDevice(p->device());
02526 root->setPrintingMode(true);
02527 root->setWidth(rc.width());
02528
02529 p->save();
02530 p->setClipRect(rc);
02531 p->translate(rc.left(), rc.top());
02532 double scale = ((double) rc.width()/(double) root->docWidth());
02533 int height = (int) ((double) rc.height() / scale);
02534 #ifndef QT_NO_TRANSFORMATIONS
02535 p->scale(scale, scale);
02536 #endif
02537
02538 root->layer()->paint(p, QRect(0, yOff, root->docWidth(), height));
02539 if (more)
02540 *more = yOff + height < root->docHeight();
02541 p->restore();
02542
02543 root->setPrintingMode(false);
02544 m_part->xmlDocImpl()->setPaintDevice( this );
02545 }
02546
02547
02548 void KHTMLView::useSlowRepaints()
02549 {
02550 d->useSlowRepaints = true;
02551 setStaticBackground(true);
02552 }
02553
02554
02555 void KHTMLView::setVScrollBarMode ( ScrollBarMode mode )
02556 {
02557 #ifndef KHTML_NO_SCROLLBARS
02558 d->vmode = mode;
02559 QScrollView::setVScrollBarMode(mode);
02560 #else
02561 Q_UNUSED( mode );
02562 #endif
02563 }
02564
02565 void KHTMLView::setHScrollBarMode ( ScrollBarMode mode )
02566 {
02567 #ifndef KHTML_NO_SCROLLBARS
02568 d->hmode = mode;
02569 QScrollView::setHScrollBarMode(mode);
02570 #else
02571 Q_UNUSED( mode );
02572 #endif
02573 }
02574
02575 void KHTMLView::restoreScrollBar()
02576 {
02577 int ow = visibleWidth();
02578 QScrollView::setVScrollBarMode(d->vmode);
02579 if (visibleWidth() != ow)
02580 layout();
02581 d->prevScrollbarVisible = verticalScrollBar()->isVisible();
02582 }
02583
02584 QStringList KHTMLView::formCompletionItems(const QString &name) const
02585 {
02586 if (!m_part->settings()->isFormCompletionEnabled())
02587 return QStringList();
02588 if (!d->formCompletions)
02589 d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
02590 return d->formCompletions->readListEntry(name);
02591 }
02592
02593 void KHTMLView::clearCompletionHistory(const QString& name)
02594 {
02595 if (!d->formCompletions)
02596 {
02597 d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
02598 }
02599 d->formCompletions->writeEntry(name, "");
02600 d->formCompletions->sync();
02601 }
02602
02603 void KHTMLView::addFormCompletionItem(const QString &name, const QString &value)
02604 {
02605 if (!m_part->settings()->isFormCompletionEnabled())
02606 return;
02607
02608
02609
02610 bool cc_number(true);
02611 for (unsigned int i = 0; i < value.length(); ++i)
02612 {
02613 QChar c(value[i]);
02614 if (!c.isNumber() && c != '-' && !c.isSpace())
02615 {
02616 cc_number = false;
02617 break;
02618 }
02619 }
02620 if (cc_number)
02621 return;
02622 QStringList items = formCompletionItems(name);
02623 if (!items.contains(value))
02624 items.prepend(value);
02625 while ((int)items.count() > m_part->settings()->maxFormCompletionItems())
02626 items.remove(items.fromLast());
02627 d->formCompletions->writeEntry(name, items);
02628 }
02629
02630 void KHTMLView::addNonPasswordStorableSite(const QString& host)
02631 {
02632 if (!d->formCompletions) {
02633 d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
02634 }
02635
02636 d->formCompletions->setGroup("NonPasswordStorableSites");
02637 QStringList sites = d->formCompletions->readListEntry("Sites");
02638 sites.append(host);
02639 d->formCompletions->writeEntry("Sites", sites);
02640 d->formCompletions->sync();
02641 d->formCompletions->setGroup(QString::null);
02642 }
02643
02644 bool KHTMLView::nonPasswordStorableSite(const QString& host) const
02645 {
02646 if (!d->formCompletions) {
02647 d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
02648 }
02649 d->formCompletions->setGroup("NonPasswordStorableSites");
02650 QStringList sites = d->formCompletions->readListEntry("Sites");
02651 d->formCompletions->setGroup(QString::null);
02652
02653 return (sites.find(host) != sites.end());
02654 }
02655
02656
02657 bool KHTMLView::dispatchMouseEvent(int eventId, DOM::NodeImpl *targetNode,
02658 DOM::NodeImpl *targetNodeNonShared, bool cancelable,
02659 int detail,QMouseEvent *_mouse, bool setUnder,
02660 int mouseEventType)
02661 {
02662 if (d->underMouse)
02663 d->underMouse->deref();
02664 d->underMouse = targetNode;
02665 if (d->underMouse)
02666 d->underMouse->ref();
02667
02668 if (d->underMouseNonShared)
02669 d->underMouseNonShared->deref();
02670 d->underMouseNonShared = targetNodeNonShared;
02671 if (d->underMouseNonShared)
02672 d->underMouseNonShared->ref();
02673
02674 int exceptioncode = 0;
02675 int pageX = 0;
02676 int pageY = 0;
02677 viewportToContents(_mouse->x(), _mouse->y(), pageX, pageY);
02678 int clientX = pageX - contentsX();
02679 int clientY = pageY - contentsY();
02680 int screenX = _mouse->globalX();
02681 int screenY = _mouse->globalY();
02682 int button = -1;
02683 switch (_mouse->button()) {
02684 case LeftButton:
02685 button = 0;
02686 break;
02687 case MidButton:
02688 button = 1;
02689 break;
02690 case RightButton:
02691 button = 2;
02692 break;
02693 default:
02694 break;
02695 }
02696 if (d->accessKeysPreActivate && button!=-1)
02697 d->accessKeysPreActivate=false;
02698
02699 bool ctrlKey = (_mouse->state() & ControlButton);
02700 bool altKey = (_mouse->state() & AltButton);
02701 bool shiftKey = (_mouse->state() & ShiftButton);
02702 bool metaKey = (_mouse->state() & MetaButton);
02703
02704
02705 if (setUnder && (d->prevMouseX != pageX || d->prevMouseY != pageY)) {
02706
02707
02708
02709 NodeImpl *oldUnder = 0;
02710 if (d->prevMouseX >= 0 && d->prevMouseY >= 0) {
02711 NodeImpl::MouseEvent mev( _mouse->stateAfter(), static_cast<NodeImpl::MouseEventType>(mouseEventType));
02712 m_part->xmlDocImpl()->prepareMouseEvent( true, d->prevMouseX, d->prevMouseY, &mev );
02713 oldUnder = mev.innerNode.handle();
02714 }
02715
02716 if (oldUnder != targetNode) {
02717
02718 if (oldUnder){
02719 oldUnder->ref();
02720 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOUT_EVENT,
02721 true,true,m_part->xmlDocImpl()->defaultView(),
02722 0,screenX,screenY,clientX,clientY,pageX, pageY,
02723 ctrlKey,altKey,shiftKey,metaKey,
02724 button,targetNode);
02725 me->ref();
02726 oldUnder->dispatchEvent(me,exceptioncode,true);
02727 me->deref();
02728 }
02729
02730
02731 if (targetNode) {
02732 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOVER_EVENT,
02733 true,true,m_part->xmlDocImpl()->defaultView(),
02734 0,screenX,screenY,clientX,clientY,pageX, pageY,
02735 ctrlKey,altKey,shiftKey,metaKey,
02736 button,oldUnder);
02737
02738 me->ref();
02739 targetNode->dispatchEvent(me,exceptioncode,true);
02740 me->deref();
02741 }
02742
02743 if (oldUnder)
02744 oldUnder->deref();
02745 }
02746 }
02747
02748 bool swallowEvent = false;
02749
02750 if (targetNode) {
02751
02752 bool dblclick = ( eventId == EventImpl::CLICK_EVENT &&
02753 _mouse->type() == QEvent::MouseButtonDblClick );
02754 MouseEventImpl *me = new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
02755 true,cancelable,m_part->xmlDocImpl()->defaultView(),
02756 detail,screenX,screenY,clientX,clientY,pageX, pageY,
02757 ctrlKey,altKey,shiftKey,metaKey,
02758 button,0, _mouse, dblclick );
02759 me->ref();
02760 targetNode->dispatchEvent(me,exceptioncode,true);
02761 if (me->defaultHandled() || me->defaultPrevented())
02762 swallowEvent = true;
02763 me->deref();
02764
02765 if (eventId == EventImpl::MOUSEDOWN_EVENT) {
02766
02767
02768
02769
02770 DOM::NodeImpl* nodeImpl = targetNode;
02771 for ( ; nodeImpl && !nodeImpl->isFocusable(); nodeImpl = nodeImpl->parentNode());
02772 if (nodeImpl && nodeImpl->isMouseFocusable())
02773 m_part->xmlDocImpl()->setFocusNode(nodeImpl);
02774 else if (!nodeImpl || !nodeImpl->focused())
02775 m_part->xmlDocImpl()->setFocusNode(0);
02776 }
02777 }
02778
02779 return swallowEvent;
02780 }
02781
02782 void KHTMLView::setIgnoreWheelEvents( bool e )
02783 {
02784 d->ignoreWheelEvents = e;
02785 }
02786
02787 #ifndef QT_NO_WHEELEVENT
02788
02789 void KHTMLView::viewportWheelEvent(QWheelEvent* e)
02790 {
02791 if (d->accessKeysPreActivate) d->accessKeysPreActivate=false;
02792
02793 if ( ( e->state() & ControlButton) == ControlButton )
02794 {
02795 emit zoomView( - e->delta() );
02796 e->accept();
02797 }
02798 else if (d->firstRelayout)
02799 {
02800 e->accept();
02801 }
02802 else if( ( (e->orientation() == Vertical &&
02803 ((d->ignoreWheelEvents && !verticalScrollBar()->isVisible())
02804 || e->delta() > 0 && contentsY() <= 0
02805 || e->delta() < 0 && contentsY() >= contentsHeight() - visibleHeight()))
02806 ||
02807 (e->orientation() == Horizontal &&
02808 ((d->ignoreWheelEvents && !horizontalScrollBar()->isVisible())
02809 || e->delta() > 0 && contentsX() <=0
02810 || e->delta() < 0 && contentsX() >= contentsWidth() - visibleWidth())))
02811 && m_part->parentPart())
02812 {
02813 if ( m_part->parentPart()->view() )
02814 m_part->parentPart()->view()->wheelEvent( e );
02815 e->ignore();
02816 }
02817 else if ( (e->orientation() == Vertical && d->vmode == QScrollView::AlwaysOff) ||
02818 (e->orientation() == Horizontal && d->hmode == QScrollView::AlwaysOff) )
02819 {
02820 e->accept();
02821 }
02822 else
02823 {
02824 d->scrollBarMoved = true;
02825 #ifndef NO_SMOOTH_SCROLL_HACK
02826 scrollViewWheelEvent( e );
02827 #else
02828 QScrollView::viewportWheelEvent( e );
02829 #endif
02830
02831 QMouseEvent *tempEvent = new QMouseEvent( QEvent::MouseMove, QPoint(-1,-1), QPoint(-1,-1), Qt::NoButton, e->state() );
02832 emit viewportMouseMoveEvent ( tempEvent );
02833 delete tempEvent;
02834 }
02835
02836 }
02837 #endif
02838
02839 void KHTMLView::dragEnterEvent( QDragEnterEvent* ev )
02840 {
02841
02842
02843
02844 if ( m_part->parentPart() )
02845 {
02846 QApplication::sendEvent(m_part->parentPart()->widget(), ev);
02847 return;
02848 }
02849 QScrollView::dragEnterEvent( ev );
02850 }
02851
02852 void KHTMLView::dropEvent( QDropEvent *ev )
02853 {
02854
02855
02856
02857 if ( m_part->parentPart() )
02858 {
02859 QApplication::sendEvent(m_part->parentPart()->widget(), ev);
02860 return;
02861 }
02862 QScrollView::dropEvent( ev );
02863 }
02864
02865 void KHTMLView::focusInEvent( QFocusEvent *e )
02866 {
02867 DOM::NodeImpl* fn = m_part->xmlDocImpl() ? m_part->xmlDocImpl()->focusNode() : 0;
02868 if (fn && fn->renderer() && fn->renderer()->isWidget() &&
02869 (e->reason() != QFocusEvent::Mouse) &&
02870 static_cast<khtml::RenderWidget*>(fn->renderer())->widget())
02871 static_cast<khtml::RenderWidget*>(fn->renderer())->widget()->setFocus();
02872 #ifndef KHTML_NO_CARET
02873
02874
02875 if (d->m_caretViewContext &&
02876 d->m_caretViewContext->freqTimerId == -1 &&
02877 fn) {
02878 if (m_part->isCaretMode()
02879 || m_part->isEditable()
02880 || (fn && fn->renderer()
02881 && fn->renderer()->style()->userInput()
02882 == UI_ENABLED)) {
02883 d->m_caretViewContext->freqTimerId = startTimer(500);
02884 d->m_caretViewContext->visible = true;
02885 }
02886 }
02887 showCaret();
02888 #endif // KHTML_NO_CARET
02889 QScrollView::focusInEvent( e );
02890 }
02891
02892 void KHTMLView::focusOutEvent( QFocusEvent *e )
02893 {
02894 if(m_part) m_part->stopAutoScroll();
02895
02896 #ifndef KHTML_NO_TYPE_AHEAD_FIND
02897 if(d->typeAheadActivated)
02898 {
02899 findTimeout();
02900 }
02901 #endif // KHTML_NO_TYPE_AHEAD_FIND
02902
02903 #ifndef KHTML_NO_CARET
02904 if (d->m_caretViewContext) {
02905 switch (d->m_caretViewContext->displayNonFocused) {
02906 case KHTMLPart::CaretInvisible:
02907 hideCaret();
02908 break;
02909 case KHTMLPart::CaretVisible: {
02910 killTimer(d->m_caretViewContext->freqTimerId);
02911 d->m_caretViewContext->freqTimerId = -1;
02912 NodeImpl *caretNode = m_part->xmlDocImpl()->focusNode();
02913 if (!d->m_caretViewContext->visible && (m_part->isCaretMode()
02914 || m_part->isEditable()
02915 || (caretNode && caretNode->renderer()
02916 && caretNode->renderer()->style()->userInput()
02917 == UI_ENABLED))) {
02918 d->m_caretViewContext->visible = true;
02919 showCaret(true);
02920 }
02921 break;
02922 }
02923 case KHTMLPart::CaretBlink:
02924
02925 break;
02926 }
02927 }
02928 #endif // KHTML_NO_CARET
02929
02930 if ( d->cursor_icon_widget )
02931 d->cursor_icon_widget->hide();
02932
02933 QScrollView::focusOutEvent( e );
02934 }
02935
02936 void KHTMLView::slotScrollBarMoved()
02937 {
02938 if ( !d->firstRelayout && !d->complete && m_part->xmlDocImpl() &&
02939 d->layoutSchedulingEnabled) {
02940
02941 khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>( m_part->xmlDocImpl()->renderer() );
02942 if (root && root->needsLayout()) {
02943 unscheduleRelayout();
02944 layout();
02945 }
02946 }
02947 if (!d->scrollingSelf) {
02948 d->scrollBarMoved = true;
02949 d->contentsMoving = true;
02950
02951 scheduleRepaint(0, 0, 0, 0);
02952 }
02953 }
02954
02955 void KHTMLView::timerEvent ( QTimerEvent *e )
02956 {
02957
02958 if ( e->timerId() == d->scrollTimerId ) {
02959 if( d->scrollSuspended )
02960 return;
02961 switch (d->scrollDirection) {
02962 case KHTMLViewPrivate::ScrollDown:
02963 if (contentsY() + visibleHeight () >= contentsHeight())
02964 d->newScrollTimer(this, 0);
02965 else
02966 scrollBy( 0, d->scrollBy );
02967 break;
02968 case KHTMLViewPrivate::ScrollUp:
02969 if (contentsY() <= 0)
02970 d->newScrollTimer(this, 0);
02971 else
02972 scrollBy( 0, -d->scrollBy );
02973 break;
02974 case KHTMLViewPrivate::ScrollRight:
02975 if (contentsX() + visibleWidth () >= contentsWidth())
02976 d->newScrollTimer(this, 0);
02977 else
02978 scrollBy( d->scrollBy, 0 );
02979 break;
02980 case KHTMLViewPrivate::ScrollLeft:
02981 if (contentsX() <= 0)
02982 d->newScrollTimer(this, 0);
02983 else
02984 scrollBy( -d->scrollBy, 0 );
02985 break;
02986 }
02987 return;
02988 }
02989 else if ( e->timerId() == d->layoutTimerId ) {
02990 d->dirtyLayout = true;
02991 layout();
02992 if (d->firstRelayout) {
02993 d->firstRelayout = false;
02994 verticalScrollBar()->setEnabled( true );
02995 horizontalScrollBar()->setEnabled( true );
02996 }
02997 }
02998 #ifndef KHTML_NO_CARET
02999 else if (d->m_caretViewContext
03000 && e->timerId() == d->m_caretViewContext->freqTimerId) {
03001 d->m_caretViewContext->visible = !d->m_caretViewContext->visible;
03002 if (d->m_caretViewContext->displayed) {
03003 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03004 d->m_caretViewContext->width,
03005 d->m_caretViewContext->height);
03006 }
03007
03008
03009 return;
03010 }
03011 #endif
03012
03013 d->contentsMoving = false;
03014 if( m_part->xmlDocImpl() ) {
03015 DOM::DocumentImpl *document = m_part->xmlDocImpl();
03016 khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer());
03017
03018 if ( root && root->needsLayout() ) {
03019 killTimer(d->repaintTimerId);
03020 d->repaintTimerId = 0;
03021 scheduleRelayout();
03022 return;
03023 }
03024 }
03025
03026 setStaticBackground(d->useSlowRepaints);
03027
03028
03029 killTimer(d->repaintTimerId);
03030 d->repaintTimerId = 0;
03031
03032 QRegion updateRegion;
03033 QMemArray<QRect> rects = d->updateRegion.rects();
03034
03035 d->updateRegion = QRegion();
03036
03037 if ( rects.size() )
03038 updateRegion = rects[0];
03039
03040 for ( unsigned i = 1; i < rects.size(); ++i ) {
03041 QRect obR = updateRegion.boundingRect();
03042 QRegion newRegion = updateRegion.unite(rects[i]);
03043 if (2*newRegion.boundingRect().height() > 3*obR.height() )
03044 {
03045 repaintContents( obR );
03046 updateRegion = rects[i];
03047 }
03048 else
03049 updateRegion = newRegion;
03050 }
03051
03052 if ( !updateRegion.isNull() )
03053 repaintContents( updateRegion.boundingRect() );
03054
03055 if (d->dirtyLayout && !d->visibleWidgets.isEmpty()) {
03056 QWidget* w;
03057 d->dirtyLayout = false;
03058
03059 QRect visibleRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
03060 QPtrList<RenderWidget> toRemove;
03061 for (QPtrDictIterator<QWidget> it(d->visibleWidgets); it.current(); ++it) {
03062 int xp = 0, yp = 0;
03063 w = it.current();
03064 RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
03065 if (!rw->absolutePosition(xp, yp) ||
03066 !visibleRect.intersects(QRect(xp, yp, w->width(), w->height())))
03067 toRemove.append(rw);
03068 }
03069 for (RenderWidget* r = toRemove.first(); r; r = toRemove.next())
03070 if ( (w = d->visibleWidgets.take(r) ) )
03071 addChild(w, 0, -500000);
03072 }
03073 if (d->accessKeysActivated) emit repaintAccessKeys();
03074 if (d->emitCompletedAfterRepaint) {
03075 if (d->emitCompletedAfterRepaint == KHTMLViewPrivate::CSFull)
03076 emit m_part->completed();
03077 else
03078 emit m_part->completed(true);
03079 d->emitCompletedAfterRepaint = KHTMLViewPrivate::CSNone;
03080 }
03081 }
03082
03083 void KHTMLView::scheduleRelayout(khtml::RenderObject * )
03084 {
03085 if (!d->layoutSchedulingEnabled || d->layoutTimerId)
03086 return;
03087
03088 d->layoutTimerId = startTimer( m_part->xmlDocImpl() && m_part->xmlDocImpl()->parsing()
03089 ? 1000 : 0 );
03090 }
03091
03092 void KHTMLView::unscheduleRelayout()
03093 {
03094 if (!d->layoutTimerId)
03095 return;
03096
03097 killTimer(d->layoutTimerId);
03098 d->layoutTimerId = 0;
03099 }
03100
03101 void KHTMLView::unscheduleRepaint()
03102 {
03103 if (!d->repaintTimerId)
03104 return;
03105
03106 killTimer(d->repaintTimerId);
03107 d->repaintTimerId = 0;
03108 }
03109
03110 void KHTMLView::scheduleRepaint(int x, int y, int w, int h, bool asap)
03111 {
03112 bool parsing = !m_part->xmlDocImpl() || m_part->xmlDocImpl()->parsing();
03113
03114
03115
03116
03117 int time = parsing ? 300 : (!asap ? ( !d->complete ? 100 : 20 ) : 0);
03118
03119 #ifdef DEBUG_FLICKER
03120 QPainter p;
03121 p.begin( viewport() );
03122
03123 int vx, vy;
03124 contentsToViewport( x, y, vx, vy );
03125 p.fillRect( vx, vy, w, h, Qt::red );
03126 p.end();
03127 #endif
03128
03129 d->updateRegion = d->updateRegion.unite(QRect(x,y,w,h));
03130
03131 if (asap && !parsing)
03132 unscheduleRelayout();
03133
03134 if ( !d->repaintTimerId )
03135 d->repaintTimerId = startTimer( time );
03136
03137
03138 }
03139
03140 void KHTMLView::complete( bool pendingAction )
03141 {
03142
03143
03144 d->complete = true;
03145
03146
03147 if (d->layoutTimerId)
03148 {
03149
03150
03151 killTimer(d->layoutTimerId);
03152 d->layoutTimerId = startTimer( 0 );
03153 d->emitCompletedAfterRepaint = pendingAction ?
03154 KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull;
03155 }
03156
03157
03158 if (d->repaintTimerId)
03159 {
03160
03161
03162 killTimer(d->repaintTimerId);
03163 d->repaintTimerId = startTimer( 20 );
03164 d->emitCompletedAfterRepaint = pendingAction ?
03165 KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull;
03166 }
03167
03168 if (!d->emitCompletedAfterRepaint)
03169 {
03170 if (!pendingAction)
03171 emit m_part->completed();
03172 else
03173 emit m_part->completed(true);
03174 }
03175
03176 }
03177
03178 void KHTMLView::slotMouseScrollTimer()
03179 {
03180 scrollBy( d->m_mouseScroll_byX, d->m_mouseScroll_byY );
03181 }
03182
03183 #ifndef KHTML_NO_CARET
03184
03185
03186
03187
03188 #include "khtml_caret.cpp"
03189
03190 void KHTMLView::initCaret(bool keepSelection)
03191 {
03192 #if DEBUG_CARETMODE > 0
03193 kdDebug(6200) << "begin initCaret" << endl;
03194 #endif
03195
03196 if (m_part->xmlDocImpl()) {
03197 #if 0
03198 ElementImpl *listitem = m_part->xmlDocImpl()->getElementById("__test_element__");
03199 if (listitem) dumpLineBoxes(static_cast<RenderFlow *>(listitem->renderer()));
03200 #endif
03201 d->caretViewContext();
03202 bool cmoved = d->m_caretViewContext->caretMoved;
03203 if (m_part->d->caretNode().isNull()) {
03204
03205 m_part->d->caretNode() = m_part->document();
03206 m_part->d->caretOffset() = 0L;
03207
03208
03209
03210 if (!m_part->d->caretNode().handle()->renderer()) return;
03211 }
03212
03213
03214
03215 moveCaretTo(m_part->d->caretNode().handle(), m_part->d->caretOffset(), !keepSelection);
03216
03217
03218 d->m_caretViewContext->caretMoved = cmoved;
03219 }
03220 #if DEBUG_CARETMODE > 0
03221 kdDebug(6200) << "end initCaret" << endl;
03222 #endif
03223 }
03224
03225 bool KHTMLView::caretOverrides() const
03226 {
03227 bool cm = m_part->isCaretMode();
03228 bool dm = m_part->isEditable();
03229 return cm && !dm ? false
03230 : (dm || m_part->d->caretNode().handle()->contentEditable())
03231 && d->editorContext()->override;
03232 }
03233
03234 void KHTMLView::ensureNodeHasFocus(NodeImpl *node)
03235 {
03236 if (m_part->isCaretMode() || m_part->isEditable()) return;
03237 if (node->focused()) return;
03238
03239
03240 NodeImpl *firstAncestor = 0;
03241 while (node) {
03242 if (node->renderer()
03243 && node->renderer()->style()->userInput() != UI_ENABLED)
03244 break;
03245 firstAncestor = node;
03246 node = node->parentNode();
03247 }
03248
03249 if (!node) firstAncestor = 0;
03250
03251 DocumentImpl *doc = m_part->xmlDocImpl();
03252
03253 if (!firstAncestor && doc->focusNode() && doc->focusNode()->renderer()
03254 && doc->focusNode()->renderer()->isWidget())
03255 return;
03256
03257
03258 #if DEBUG_CARETMODE > 1
03259 kdDebug(6200) << k_funcinfo << "firstAncestor " << firstAncestor << ": "
03260 << (firstAncestor ? firstAncestor->nodeName().string() : QString::null) << endl;
03261 #endif
03262 doc->setFocusNode(firstAncestor);
03263 emit m_part->nodeActivated(Node(firstAncestor));
03264 }
03265
03266 void KHTMLView::recalcAndStoreCaretPos(CaretBox *hintBox)
03267 {
03268 if (!m_part || m_part->d->caretNode().isNull()) return;
03269 d->caretViewContext();
03270 NodeImpl *caretNode = m_part->d->caretNode().handle();
03271 #if DEBUG_CARETMODE > 0
03272 kdDebug(6200) << "recalcAndStoreCaretPos: caretNode=" << caretNode << (caretNode ? " "+caretNode->nodeName().string() : QString::null) << " r@" << caretNode->renderer() << (caretNode->renderer() && caretNode->renderer()->isText() ? " \"" + QConstString(static_cast<RenderText *>(caretNode->renderer())->str->s, kMin(static_cast<RenderText *>(caretNode->renderer())->str->l, 15u)).string() + "\"" : QString::null) << endl;
03273 #endif
03274 caretNode->getCaret(m_part->d->caretOffset(), caretOverrides(),
03275 d->m_caretViewContext->x, d->m_caretViewContext->y,
03276 d->m_caretViewContext->width,
03277 d->m_caretViewContext->height);
03278
03279 if (hintBox && d->m_caretViewContext->x == -1) {
03280 #if DEBUG_CARETMODE > 1
03281 kdDebug(6200) << "using hint inline box coordinates" << endl;
03282 #endif
03283 RenderObject *r = caretNode->renderer();
03284 const QFontMetrics &fm = r->style()->fontMetrics();
03285 int absx, absy;
03286 r->containingBlock()->absolutePosition(absx, absy,
03287 false);
03288 d->m_caretViewContext->x = absx + hintBox->xPos();
03289 d->m_caretViewContext->y = absy + hintBox->yPos();
03290
03291 d->m_caretViewContext->width = 1;
03292
03293
03294 d->m_caretViewContext->height = fm.height();
03295 }
03296
03297 #if DEBUG_CARETMODE > 4
03298
03299 #endif
03300 #if DEBUG_CARETMODE > 0
03301 kdDebug(6200) << "caret: ofs="<<m_part->d->caretOffset()<<" "
03302 <<" x="<<d->m_caretViewContext->x<<" y="<<d->m_caretViewContext->y
03303 <<" h="<<d->m_caretViewContext->height<<endl;
03304 #endif
03305 }
03306
03307 void KHTMLView::caretOn()
03308 {
03309 if (d->m_caretViewContext) {
03310 killTimer(d->m_caretViewContext->freqTimerId);
03311
03312 if (hasFocus() || d->m_caretViewContext->displayNonFocused
03313 == KHTMLPart::CaretBlink) {
03314 d->m_caretViewContext->freqTimerId = startTimer(500);
03315 } else {
03316 d->m_caretViewContext->freqTimerId = -1;
03317 }
03318
03319 d->m_caretViewContext->visible = true;
03320 if ((d->m_caretViewContext->displayed = (hasFocus()
03321 || d->m_caretViewContext->displayNonFocused
03322 != KHTMLPart::CaretInvisible))) {
03323 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03324 d->m_caretViewContext->width,
03325 d->m_caretViewContext->height);
03326 }
03327
03328 }
03329 }
03330
03331 void KHTMLView::caretOff()
03332 {
03333 if (d->m_caretViewContext) {
03334 killTimer(d->m_caretViewContext->freqTimerId);
03335 d->m_caretViewContext->freqTimerId = -1;
03336 d->m_caretViewContext->displayed = false;
03337 if (d->m_caretViewContext->visible) {
03338 d->m_caretViewContext->visible = false;
03339 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03340 d->m_caretViewContext->width,
03341 d->m_caretViewContext->height);
03342 }
03343
03344 }
03345 }
03346
03347 void KHTMLView::showCaret(bool forceRepaint)
03348 {
03349 if (d->m_caretViewContext) {
03350 d->m_caretViewContext->displayed = true;
03351 if (d->m_caretViewContext->visible) {
03352 if (!forceRepaint) {
03353 updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03354 d->m_caretViewContext->width,
03355 d->m_caretViewContext->height);
03356 } else {
03357 repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03358 d->m_caretViewContext->width,
03359 d->m_caretViewContext->height);
03360 }
03361 }
03362
03363 }
03364 }
03365
03366 bool KHTMLView::foldSelectionToCaret(NodeImpl *startNode, long startOffset,
03367 NodeImpl *endNode, long endOffset)
03368 {
03369 m_part->d->m_selectionStart = m_part->d->m_selectionEnd = m_part->d->caretNode();
03370 m_part->d->m_startOffset = m_part->d->m_endOffset = m_part->d->caretOffset();
03371 m_part->d->m_extendAtEnd = true;
03372
03373 bool folded = startNode != endNode || startOffset != endOffset;
03374
03375
03376 if (folded) {
03377 m_part->xmlDocImpl()->clearSelection();
03378 }
03379
03380 return folded;
03381 }
03382
03383 void KHTMLView::hideCaret()
03384 {
03385 if (d->m_caretViewContext) {
03386 if (d->m_caretViewContext->visible) {
03387
03388 d->m_caretViewContext->visible = false;
03389
03390
03391 repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
03392 d->m_caretViewContext->width,
03393 d->m_caretViewContext->height);
03394 d->m_caretViewContext->visible = true;
03395 }
03396 d->m_caretViewContext->displayed = false;
03397
03398 }
03399 }
03400
03401 int KHTMLView::caretDisplayPolicyNonFocused() const
03402 {
03403 if (d->m_caretViewContext)
03404 return d->m_caretViewContext->displayNonFocused;
03405 else
03406 return KHTMLPart::CaretInvisible;
03407 }
03408
03409 void KHTMLView::setCaretDisplayPolicyNonFocused(int policy)
03410 {
03411 d->caretViewContext();
03412
03413 d->m_caretViewContext->displayNonFocused = (KHTMLPart::CaretDisplayPolicy)policy;
03414
03415
03416 if (!hasFocus()) {
03417 switch (d->m_caretViewContext->displayNonFocused) {
03418 case KHTMLPart::CaretInvisible:
03419 hideCaret();
03420 break;
03421 case KHTMLPart::CaretBlink:
03422 if (d->m_caretViewContext->freqTimerId != -1) break;
03423 d->m_caretViewContext->freqTimerId = startTimer(500);
03424
03425 case KHTMLPart::CaretVisible:
03426 d->m_caretViewContext->displayed = true;
03427 showCaret();
03428 break;
03429 }
03430 }
03431 }
03432
03433 bool KHTMLView::placeCaret(CaretBox *hintBox)
03434 {
03435 CaretViewContext *cv = d->caretViewContext();
03436 caretOff();
03437 NodeImpl *caretNode = m_part->d->caretNode().handle();
03438
03439 if (!caretNode || !caretNode->renderer()) return false;
03440 ensureNodeHasFocus(caretNode);
03441 if (m_part->isCaretMode() || m_part->isEditable()
03442 || caretNode->renderer()->style()->userInput() == UI_ENABLED) {
03443 recalcAndStoreCaretPos(hintBox);
03444
03445 cv->origX = cv->x;
03446
03447 caretOn();
03448 return true;
03449 }
03450 return false;
03451 }
03452
03453 void KHTMLView::ensureCaretVisible()
03454 {
03455 CaretViewContext *cv = d->m_caretViewContext;
03456 if (!cv) return;
03457 ensureVisible(cv->x, cv->y, cv->width, cv->height);
03458 d->scrollBarMoved = false;
03459 }
03460
03461 bool KHTMLView::extendSelection(NodeImpl *oldStartSel, long oldStartOfs,
03462 NodeImpl *oldEndSel, long oldEndOfs)
03463 {
03464 bool changed = false;
03465 if (m_part->d->m_selectionStart == m_part->d->m_selectionEnd
03466 && m_part->d->m_startOffset == m_part->d->m_endOffset) {
03467 changed = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
03468 m_part->d->m_extendAtEnd = true;
03469 } else do {
03470 changed = m_part->d->m_selectionStart.handle() != oldStartSel
03471 || m_part->d->m_startOffset != oldStartOfs
03472 || m_part->d->m_selectionEnd.handle() != oldEndSel
03473 || m_part->d->m_endOffset != oldEndOfs;
03474 if (!changed) break;
03475
03476
03477 NodeImpl *startNode;
03478 long startOffset;
03479 if (m_part->d->m_extendAtEnd) {
03480 startNode = m_part->d->m_selectionStart.handle();
03481 startOffset = m_part->d->m_startOffset;
03482 } else {
03483 startNode = m_part->d->m_selectionEnd.handle();
03484 startOffset = m_part->d->m_endOffset;
03485 m_part->d->m_selectionEnd = m_part->d->m_selectionStart;
03486 m_part->d->m_endOffset = m_part->d->m_startOffset;
03487 m_part->d->m_extendAtEnd = true;
03488 }
03489
03490 bool swapNeeded = false;
03491 if (!m_part->d->m_selectionEnd.isNull() && startNode) {
03492 swapNeeded = RangeImpl::compareBoundaryPoints(startNode, startOffset,
03493 m_part->d->m_selectionEnd.handle(),
03494 m_part->d->m_endOffset) >= 0;
03495 }
03496
03497 m_part->d->m_selectionStart = startNode;
03498 m_part->d->m_startOffset = startOffset;
03499
03500 if (swapNeeded) {
03501 m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionEnd.handle(),
03502 m_part->d->m_endOffset, m_part->d->m_selectionStart.handle(),
03503 m_part->d->m_startOffset);
03504 } else {
03505 m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionStart.handle(),
03506 m_part->d->m_startOffset, m_part->d->m_selectionEnd.handle(),
03507 m_part->d->m_endOffset);
03508 }
03509 } while(false);
03510 return changed;
03511 }
03512
03513 void KHTMLView::updateSelection(NodeImpl *oldStartSel, long oldStartOfs,
03514 NodeImpl *oldEndSel, long oldEndOfs)
03515 {
03516 if (m_part->d->m_selectionStart == m_part->d->m_selectionEnd
03517 && m_part->d->m_startOffset == m_part->d->m_endOffset) {
03518 if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs)) {
03519 m_part->emitSelectionChanged();
03520 }
03521 m_part->d->m_extendAtEnd = true;
03522 } else {
03523
03524 if (!m_part->d->m_selectionEnd.isNull() && !m_part->d->m_selectionEnd.isNull()) {
03525 bool swapNeeded = RangeImpl::compareBoundaryPoints(
03526 m_part->d->m_selectionStart.handle(), m_part->d->m_startOffset,
03527 m_part->d->m_selectionEnd.handle(), m_part->d->m_endOffset) >= 0;
03528 if (swapNeeded) {
03529 DOM::Node tmpNode = m_part->d->m_selectionStart;
03530 long tmpOffset = m_part->d->m_startOffset;
03531 m_part->d->m_selectionStart = m_part->d->m_selectionEnd;
03532 m_part->d->m_startOffset = m_part->d->m_endOffset;
03533 m_part->d->m_selectionEnd = tmpNode;
03534 m_part->d->m_endOffset = tmpOffset;
03535 m_part->d->m_startBeforeEnd = true;
03536 m_part->d->m_extendAtEnd = !m_part->d->m_extendAtEnd;
03537 }
03538 }
03539
03540 m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionStart.handle(),
03541 m_part->d->m_startOffset, m_part->d->m_selectionEnd.handle(),
03542 m_part->d->m_endOffset);
03543 m_part->emitSelectionChanged();
03544 }
03545 }
03546
03547 void KHTMLView::caretKeyPressEvent(QKeyEvent *_ke)
03548 {
03549 NodeImpl *oldStartSel = m_part->d->m_selectionStart.handle();
03550 long oldStartOfs = m_part->d->m_startOffset;
03551 NodeImpl *oldEndSel = m_part->d->m_selectionEnd.handle();
03552 long oldEndOfs = m_part->d->m_endOffset;
03553
03554 NodeImpl *oldCaretNode = m_part->d->caretNode().handle();
03555 long oldOffset = m_part->d->caretOffset();
03556
03557 bool ctrl = _ke->state() & ControlButton;
03558
03559
03560 switch(_ke->key()) {
03561 case Key_Space:
03562 break;
03563
03564 case Key_Down:
03565 moveCaretNextLine(1);
03566 break;
03567
03568 case Key_Up:
03569 moveCaretPrevLine(1);
03570 break;
03571
03572 case Key_Left:
03573 moveCaretBy(false, ctrl ? CaretByWord : CaretByCharacter, 1);
03574 break;
03575
03576 case Key_Right:
03577 moveCaretBy(true, ctrl ? CaretByWord : CaretByCharacter, 1);
03578 break;
03579
03580 case Key_Next:
03581 moveCaretNextPage();
03582 break;
03583
03584 case Key_Prior:
03585 moveCaretPrevPage();
03586 break;
03587
03588 case Key_Home:
03589 if (ctrl)
03590 moveCaretToDocumentBoundary(false);
03591 else
03592 moveCaretToLineBegin();
03593 break;
03594
03595 case Key_End:
03596 if (ctrl)
03597 moveCaretToDocumentBoundary(true);
03598 else
03599 moveCaretToLineEnd();
03600 break;
03601
03602 }
03603
03604 if ((m_part->d->caretNode().handle() != oldCaretNode
03605 || m_part->d->caretOffset() != oldOffset)
03606
03607 && !m_part->d->caretNode().isNull()) {
03608
03609 d->m_caretViewContext->caretMoved = true;
03610
03611 if (_ke->state() & ShiftButton) {
03612 updateSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
03613 } else {
03614 if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs))
03615 m_part->emitSelectionChanged();
03616 }
03617
03618 m_part->emitCaretPositionChanged(m_part->d->caretNode(), m_part->d->caretOffset());
03619 }
03620
03621 _ke->accept();
03622 }
03623
03624 bool KHTMLView::moveCaretTo(NodeImpl *node, long offset, bool clearSel)
03625 {
03626 if (!node) return false;
03627 ElementImpl *baseElem = determineBaseElement(node);
03628 RenderFlow *base = static_cast<RenderFlow *>(baseElem ? baseElem->renderer() : 0);
03629 if (!node) return false;
03630
03631
03632
03633
03634 CaretBoxLineDeleter cblDeleter;
03635
03636 long r_ofs;
03637 CaretBoxIterator cbit;
03638 CaretBoxLine *cbl = findCaretBoxLine(node, offset, &cblDeleter, base, r_ofs, cbit);
03639 if(!cbl) {
03640 kdWarning() << "KHTMLView::moveCaretTo - findCaretBoxLine() returns NULL" << endl;
03641 return false;
03642 }
03643
03644 #if DEBUG_CARETMODE > 3
03645 if (cbl) kdDebug(6200) << cbl->information() << endl;
03646 #endif
03647 CaretBox *box = *cbit;
03648 if (cbit != cbl->end() && box->object() != node->renderer()) {
03649 if (box->object()->element()) {
03650 mapRenderPosToDOMPos(box->object(), r_ofs, box->isOutside(),
03651 box->isOutsideEnd(), node, offset);
03652
03653 #if DEBUG_CARETMODE > 1
03654 kdDebug(6200) << "set new node " << node->nodeName().string() << "@" << node << endl;
03655 #endif
03656 } else {
03657
03658 box = 0;
03659 kdError(6200) << "Box contains no node! Crash imminent" << endl;
03660 }
03661 }
03662
03663 NodeImpl *oldStartSel = m_part->d->m_selectionStart.handle();
03664 long oldStartOfs = m_part->d->m_startOffset;
03665 NodeImpl *oldEndSel = m_part->d->m_selectionEnd.handle();
03666 long oldEndOfs = m_part->d->m_endOffset;
03667
03668
03669 bool posChanged = m_part->d->caretNode().handle() != node
03670 || m_part->d->caretOffset() != offset;
03671 bool selChanged = false;
03672
03673 m_part->d->caretNode() = node;
03674 m_part->d->caretOffset() = offset;
03675 if (clearSel || !oldStartSel || !oldEndSel) {
03676 selChanged = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
03677 } else {
03678
03679
03680 selChanged = extendSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
03681
03682
03683 }
03684
03685 d->caretViewContext()->caretMoved = true;
03686
03687 bool visible_caret = placeCaret(box);
03688
03689
03690
03691
03692 if (posChanged) {
03693 m_part->emitCaretPositionChanged(visible_caret ? node : 0, offset);
03694 }
03695
03696 return selChanged;
03697 }
03698
03699 void KHTMLView::moveCaretByLine(bool next, int count)
03700 {
03701 Node &caretNodeRef = m_part->d->caretNode();
03702 if (caretNodeRef.isNull()) return;
03703
03704 NodeImpl *caretNode = caretNodeRef.handle();
03705
03706 long offset = m_part->d->caretOffset();
03707
03708 CaretViewContext *cv = d->caretViewContext();
03709
03710 ElementImpl *baseElem = determineBaseElement(caretNode);
03711 LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
03712
03713 ErgonomicEditableLineIterator it(ld.current(), cv->origX);
03714
03715
03716 while (count > 0 && it != ld.end() && it != ld.preBegin()) {
03717 count--;
03718 if (next) ++it; else --it;
03719 }
03720
03721
03722 if (it == ld.end() || it == ld.preBegin()) return;
03723
03724 int x, absx, absy;
03725 CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy);
03726
03727 placeCaretOnLine(caretBox, x, absx, absy);
03728 }
03729
03730 void KHTMLView::placeCaretOnLine(CaretBox *caretBox, int x, int absx, int absy)
03731 {
03732
03733 if (!caretBox) return;
03734
03735 RenderObject *caretRender = caretBox->object();
03736
03737 #if DEBUG_CARETMODE > 0
03738 kdDebug(6200) << "got valid caretBox " << caretBox << endl;
03739 kdDebug(6200) << "xPos: " << caretBox->xPos() << " yPos: " << caretBox->yPos()
03740 << " width: " << caretBox->width() << " height: " << caretBox->height() << endl;
03741 InlineTextBox *tb = static_cast<InlineTextBox *>(caretBox->inlineBox());
03742 if (caretBox->isInlineTextBox()) { kdDebug(6200) << "contains \"" << QString(static_cast<RenderText *>(tb->object())->str->s + tb->m_start, tb->m_len) << "\"" << endl;}
03743 #endif
03744
03745 int caretHeight = caretBox->height();
03746 bool isText = caretBox->isInlineTextBox();
03747 int yOfs = 0;
03748 if (isText) {
03749
03750 RenderText *t = static_cast<RenderText *>(caretRender);
03751 const QFontMetrics &fm = t->metrics(caretBox->inlineBox()->m_firstLine);
03752 caretHeight = fm.height();
03753 yOfs = caretBox->inlineBox()->baseline() - fm.ascent();
03754 }
03755
03756 caretOff();
03757
03758
03759 NodeImpl *caretNode;
03760 long &offset = m_part->d->caretOffset();
03761 mapRenderPosToDOMPos(caretRender, offset, caretBox->isOutside(),
03762 caretBox->isOutsideEnd(), caretNode, offset);
03763
03764
03765 d->m_caretViewContext->y = caretBox->yPos() + yOfs;
03766 d->m_caretViewContext->height = caretHeight;
03767 d->m_caretViewContext->width = 1;
03768
03769 int xPos = caretBox->xPos();
03770 int caretBoxWidth = caretBox->width();
03771 d->m_caretViewContext->x = xPos;
03772
03773 if (!caretBox->isOutside()) {
03774
03775 long r_ofs = 0;
03776 if (x <= xPos) {
03777 r_ofs = caretBox->minOffset();
03778
03779 } else if (x > xPos && x <= xPos + caretBoxWidth) {
03780 if (isText) {
03781 r_ofs = static_cast<InlineTextBox *>(caretBox->inlineBox())
03782 ->offsetForPoint(x, d->m_caretViewContext->x);
03783 #if DEBUG_CARETMODE > 2
03784 kdDebug(6200) << "deviation from origX " << d->m_caretViewContext->x - x << endl;
03785 #endif
03786 #if 0
03787 } else {
03788 if (xPos + caretBoxWidth - x < x - xPos) {
03789 d->m_caretViewContext->x = xPos + caretBoxWidth;
03790 r_ofs = caretNode ? caretNode->maxOffset() : 1;
03791 } else {
03792 d->m_caretViewContext->x = xPos;
03793 r_ofs = caretNode ? caretNode->minOffset() : 0;
03794 }
03795 #endif
03796 }
03797 } else {
03798 d->m_caretViewContext->x = xPos + caretBoxWidth;
03799 r_ofs = caretBox->maxOffset();
03800 }
03801 offset = r_ofs;
03802 }
03803 #if DEBUG_CARETMODE > 0
03804 kdDebug(6200) << "new offset: " << offset << endl;
03805 #endif
03806
03807 m_part->d->caretNode() = caretNode;
03808 m_part->d->caretOffset() = offset;
03809
03810 d->m_caretViewContext->x += absx;
03811 d->m_caretViewContext->y += absy;
03812
03813 #if DEBUG_CARETMODE > 1
03814 kdDebug(6200) << "new caret position: x " << d->m_caretViewContext->x << " y " << d->m_caretViewContext->y << " w " << d->m_caretViewContext->width << " h " << d->m_caretViewContext->height << " absx " << absx << " absy " << absy << endl;
03815 #endif
03816
03817 ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y,
03818 d->m_caretViewContext->width, d->m_caretViewContext->height);
03819 d->scrollBarMoved = false;
03820
03821 ensureNodeHasFocus(caretNode);
03822 caretOn();
03823 }
03824
03825 void KHTMLView::moveCaretToLineBoundary(bool end)
03826 {
03827 Node &caretNodeRef = m_part->d->caretNode();
03828 if (caretNodeRef.isNull()) return;
03829
03830 NodeImpl *caretNode = caretNodeRef.handle();
03831
03832 long offset = m_part->d->caretOffset();
03833
03834 ElementImpl *baseElem = determineBaseElement(caretNode);
03835 LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
03836
03837 EditableLineIterator it = ld.current();
03838 if (it == ld.end()) return;
03839
03840 EditableCaretBoxIterator fbit(it, end);
03841 Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin());
03842 CaretBox *b = *fbit;
03843
03844 RenderObject *cb = b->containingBlock();
03845 int absx, absy;
03846
03847 if (cb) cb->absolutePosition(absx,absy);
03848 else absx = absy = 0;
03849
03850 int x = b->xPos() + (end && !b->isOutside() ? b->width() : 0);
03851 d->m_caretViewContext->origX = absx + x;
03852 placeCaretOnLine(b, x, absx, absy);
03853 }
03854
03855 void KHTMLView::moveCaretToDocumentBoundary(bool end)
03856 {
03857 Node &caretNodeRef = m_part->d->caretNode();
03858 if (caretNodeRef.isNull()) return;
03859
03860 NodeImpl *caretNode = caretNodeRef.handle();
03861
03862 long offset = m_part->d->caretOffset();
03863
03864 ElementImpl *baseElem = determineBaseElement(caretNode);
03865 LinearDocument ld(m_part, caretNode, offset, IndicatedFlows, baseElem);
03866
03867 EditableLineIterator it(end ? ld.preEnd() : ld.begin(), end);
03868 if (it == ld.end() || it == ld.preBegin()) return;
03869
03870 EditableCaretBoxIterator fbit = it;
03871 Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin());
03872 CaretBox *b = *fbit;
03873
03874 RenderObject *cb = (*it)->containingBlock();
03875 int absx, absy;
03876
03877 if (cb) cb->absolutePosition(absx, absy);
03878 else absx = absy = 0;
03879
03880 int x = b->xPos();
03881 d->m_caretViewContext->origX = absx + x;
03882 placeCaretOnLine(b, x, absx, absy);
03883 }
03884
03885 void KHTMLView::moveCaretBy(bool next, CaretMovement cmv, int count)
03886 {
03887 if (!m_part) return;
03888 Node &caretNodeRef = m_part->d->caretNode();
03889 if (caretNodeRef.isNull()) return;
03890
03891 NodeImpl *caretNode = caretNodeRef.handle();
03892
03893 long &offset = m_part->d->caretOffset();
03894
03895 ElementImpl *baseElem = determineBaseElement(caretNode);
03896 CaretAdvancePolicy advpol = cmv != CaretByWord ? IndicatedFlows : LeafsOnly;
03897 LinearDocument ld(m_part, caretNode, offset, advpol, baseElem);
03898
03899 EditableCharacterIterator it(&ld);
03900 while (!it.isEnd() && count > 0) {
03901 count--;
03902 if (cmv == CaretByCharacter) {
03903 if (next) ++it;
03904 else --it;
03905 } else if (cmv == CaretByWord) {
03906 if (next) moveItToNextWord(it);
03907 else moveItToPrevWord(it);
03908 }
03909
03910 }
03911 CaretBox *hintBox = 0;
03912 if (!it.isEnd()) {
03913 NodeImpl *node = caretNodeRef.handle();
03914 hintBox = it.caretBox();
03915
03916
03917 mapRenderPosToDOMPos(it.renderer(), it.offset(), hintBox->isOutside(),
03918 hintBox->isOutsideEnd(), node, offset);
03919
03920 caretNodeRef = node;
03921 #if DEBUG_CARETMODE > 2
03922 kdDebug(6200) << "set by valid node " << node << " " << (node?node->nodeName().string():QString::null) << " offset: " << offset << endl;
03923 #endif
03924 } else {
03925 offset = next ? caretNode->maxOffset() : caretNode->minOffset();
03926 #if DEBUG_CARETMODE > 0
03927 kdDebug(6200) << "set by INvalid node. offset: " << offset << endl;
03928 #endif
03929 }
03930 placeCaretOnChar(hintBox);
03931 }
03932
03933 void KHTMLView::placeCaretOnChar(CaretBox *hintBox)
03934 {
03935 caretOff();
03936 recalcAndStoreCaretPos(hintBox);
03937 ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y,
03938 d->m_caretViewContext->width, d->m_caretViewContext->height);
03939 d->m_caretViewContext->origX = d->m_caretViewContext->x;
03940 d->scrollBarMoved = false;
03941 #if DEBUG_CARETMODE > 3
03942
03943 #endif
03944 ensureNodeHasFocus(m_part->d->caretNode().handle());
03945 caretOn();
03946 }
03947
03948 void KHTMLView::moveCaretByPage(bool next)
03949 {
03950 Node &caretNodeRef = m_part->d->caretNode();
03951
03952 NodeImpl *caretNode = caretNodeRef.handle();
03953
03954 long offset = m_part->d->caretOffset();
03955
03956 int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
03957
03958 int mindist = clipper()->height() - offs;
03959
03960 CaretViewContext *cv = d->caretViewContext();
03961
03962
03963 ElementImpl *baseElem = determineBaseElement(caretNode);
03964 LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
03965
03966 ErgonomicEditableLineIterator it(ld.current(), cv->origX);
03967
03968 moveIteratorByPage(ld, it, mindist, next);
03969
03970 int x, absx, absy;
03971 CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy);
03972
03973 placeCaretOnLine(caretBox, x, absx, absy);
03974 }
03975
03976 void KHTMLView::moveCaretPrevWord()
03977 {
03978 moveCaretBy(false, CaretByWord, 1);
03979 }
03980
03981 void KHTMLView::moveCaretNextWord()
03982 {
03983 moveCaretBy(true, CaretByWord, 1);
03984 }
03985
03986 void KHTMLView::moveCaretPrevLine(int n)
03987 {
03988 moveCaretByLine(false, n);
03989 }
03990
03991 void KHTMLView::moveCaretNextLine(int n)
03992 {
03993 moveCaretByLine(true, n);
03994 }
03995
03996 void KHTMLView::moveCaretPrevPage()
03997 {
03998 moveCaretByPage(false);
03999 }
04000
04001 void KHTMLView::moveCaretNextPage()
04002 {
04003 moveCaretByPage(true);
04004 }
04005
04006 void KHTMLView::moveCaretToLineBegin()
04007 {
04008 moveCaretToLineBoundary(false);
04009 }
04010
04011 void KHTMLView::moveCaretToLineEnd()
04012 {
04013 moveCaretToLineBoundary(true);
04014 }
04015
04016 #endif // KHTML_NO_CARET
04017
04018 #ifndef NO_SMOOTH_SCROLL_HACK
04019 #define timer timer2
04020
04021
04022 static const int SCROLL_TIME = 240;
04023
04024 static const int SCROLL_TICK = 20;
04025
04026 void KHTMLView::scrollBy(int dx, int dy)
04027 {
04028 KConfigGroup cfg( KGlobal::config(), "KDE" );
04029 if( !cfg.readBoolEntry( "SmoothScrolling", true )) {
04030 QScrollView::scrollBy( dx, dy );
04031 return;
04032 }
04033
04034 int full_dx = d->dx + dx;
04035 int full_dy = d->dy + dy;
04036
04037
04038 int ddx = 0;
04039 int ddy = 0;
04040
04041 int steps = SCROLL_TIME/SCROLL_TICK;
04042
04043 ddx = (full_dx*16)/steps;
04044 ddy = (full_dy*16)/steps;
04045
04046
04047 if (ddx > 0 && ddx < 16) ddx = 16;
04048 if (ddy > 0 && ddy < 16) ddy = 16;
04049 if (ddx < 0 && ddx > -16) ddx = -16;
04050 if (ddy < 0 && ddy > -16) ddy = -16;
04051
04052 d->dx = full_dx;
04053 d->dy = full_dy;
04054 d->ddx = ddx;
04055 d->ddy = ddy;
04056
04057 if (!d->scrolling) {
04058 scrollTick();
04059 startScrolling();
04060 }
04061 }
04062
04063 void KHTMLView::scrollTick() {
04064 if (d->dx == 0 && d->dy == 0) {
04065 stopScrolling();
04066 return;
04067 }
04068
04069 int tddx = d->ddx + d->rdx;
04070 int tddy = d->ddy + d->rdy;
04071
04072 int ddx = tddx / 16;
04073 int ddy = tddy / 16;
04074 d->rdx = tddx % 16;
04075 d->rdy = tddy % 16;
04076
04077 if (d->dx > 0 && ddx > d->dx) ddx = d->dx;
04078 else
04079 if (d->dx < 0 && ddx < d->dx) ddx = d->dx;
04080
04081 if (d->dy > 0 && ddy > d->dy) ddy = d->dy;
04082 else
04083 if (d->dy < 0 && ddy < d->dy) ddy = d->dy;
04084
04085 d->dx -= ddx;
04086 d->dy -= ddy;
04087
04088
04089 QScrollView::scrollBy(ddx, ddy);
04090 }
04091
04092 void KHTMLView::startScrolling()
04093 {
04094 d->scrolling = true;
04095 d->timer.start(SCROLL_TICK, false);
04096 }
04097
04098 void KHTMLView::stopScrolling()
04099 {
04100 d->timer.stop();
04101 d->dx = d->dy = 0;
04102 d->scrolling = false;
04103 }
04104
04105
04106 void KHTMLView::scrollViewWheelEvent( QWheelEvent *e )
04107 {
04108 int pageStep = verticalScrollBar()->pageStep();
04109 int lineStep = verticalScrollBar()->lineStep();
04110 int step = QMIN( QApplication::wheelScrollLines()*lineStep, pageStep );
04111 if ( ( e->state() & ControlButton ) || ( e->state() & ShiftButton ) )
04112 step = pageStep;
04113
04114 if(e->orientation() == Horizontal)
04115 scrollBy(-((e->delta()*step)/120), 0);
04116 else if(e->orientation() == Vertical)
04117 scrollBy(0,-((e->delta()*step)/120));
04118
04119 e->accept();
04120 }
04121
04122 #undef timer
04123
04124 #endif // NO_SMOOTH_SCROLL_HACK
04125
04126 #undef DEBUG_CARETMODE