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 "css/csshelper.h"
00051 #include "misc/htmlhashes.h"
00052 #include "misc/helper.h"
00053 #include "khtml_settings.h"
00054 #include "khtml_printsettings.h"
00055
00056 #include "khtmlpart_p.h"
00057
00058 #ifndef KHTML_NO_CARET
00059 #include "khtml_caret_p.h"
00060 #include "xml/dom2_rangeimpl.h"
00061 #endif
00062
00063 #include <kapplication.h>
00064 #include <kcursor.h>
00065 #include <kdebug.h>
00066 #include <kdialogbase.h>
00067 #include <kiconloader.h>
00068 #include <kimageio.h>
00069 #include <klocale.h>
00070 #include <knotifyclient.h>
00071 #include <kprinter.h>
00072 #include <ksimpleconfig.h>
00073 #include <kstandarddirs.h>
00074 #include <kstdaccel.h>
00075 #include <kstringhandler.h>
00076 #include <kurldrag.h>
00077
00078 #include <qbitmap.h>
00079 #include <qlabel.h>
00080 #include <qobjectlist.h>
00081 #include <qpaintdevicemetrics.h>
00082 #include <qpainter.h>
00083 #include <qptrdict.h>
00084 #include <qtooltip.h>
00085 #include <qstring.h>
00086 #include <qstylesheet.h>
00087 #include <qtimer.h>
00088 #include <qvaluevector.h>
00089
00090
00091
00092
00093
00094
00095
00096 #ifdef Q_WS_X11
00097 #include <X11/Xlib.h>
00098 #include <fixx11h.h>
00099 #endif
00100
00101 #define PAINT_BUFFER_HEIGHT 128
00102
00103 #if 0
00104 namespace khtml {
00105 void dumpLineBoxes(RenderFlow *flow);
00106 }
00107 #endif
00108
00109 using namespace DOM;
00110 using namespace khtml;
00111 class KHTMLToolTip;
00112
00113
00114 #ifndef QT_NO_TOOLTIP
00115
00116 class KHTMLToolTip : public QToolTip
00117 {
00118 public:
00119 KHTMLToolTip(KHTMLView *view, KHTMLViewPrivate* vp) : QToolTip(view->viewport())
00120 {
00121 m_view = view;
00122 m_viewprivate = vp;
00123 };
00124
00125 protected:
00126 virtual void maybeTip(const QPoint &);
00127
00128 private:
00129 KHTMLView *m_view;
00130 KHTMLViewPrivate* m_viewprivate;
00131 };
00132
00133 #endif
00134
00135 class KHTMLViewPrivate {
00136 friend class KHTMLToolTip;
00137 public:
00138
00139 enum PseudoFocusNodes {
00140 PFNone,
00141 PFTop,
00142 PFBottom
00143 };
00144
00145 enum CompletedState {
00146 CSNone = 0,
00147 CSFull,
00148 CSActionPending
00149 };
00150
00151 KHTMLViewPrivate()
00152 : underMouse( 0 ), underMouseNonShared( 0 ), visibleWidgets( 107 )
00153 {
00154 #ifndef KHTML_NO_CARET
00155 m_caretViewContext = 0;
00156 m_editorContext = 0;
00157 #endif // KHTML_NO_CARET
00158 postponed_autorepeat = NULL;
00159 reset();
00160 vmode = QScrollView::Auto;
00161 hmode = QScrollView::Auto;
00162 tp=0;
00163 paintBuffer=0;
00164 vertPaintBuffer=0;
00165 formCompletions=0;
00166 prevScrollbarVisible = true;
00167 tooltip = 0;
00168 possibleTripleClick = false;
00169 emitCompletedAfterRepaint = CSNone;
00170 cursor_icon_widget = NULL;
00171 m_mouseScrollTimer = 0;
00172 m_mouseScrollIndicator = 0;
00173 }
00174 ~KHTMLViewPrivate()
00175 {
00176 delete formCompletions;
00177 delete tp; tp = 0;
00178 delete paintBuffer; paintBuffer =0;
00179 delete vertPaintBuffer;
00180 delete postponed_autorepeat;
00181 if (underMouse)
00182 underMouse->deref();
00183 if (underMouseNonShared)
00184 underMouseNonShared->deref();
00185 delete tooltip;
00186 #ifndef KHTML_NO_CARET
00187 delete m_caretViewContext;
00188 delete m_editorContext;
00189 #endif // KHTML_NO_CARET
00190 delete cursor_icon_widget;
00191 delete m_mouseScrollTimer;
00192 delete m_mouseScrollIndicator;
00193 }
00194 void reset()
00195 {
00196 if (underMouse)
00197 underMouse->deref();
00198 underMouse = 0;
00199 if (underMouseNonShared)
00200 underMouseNonShared->deref();
00201 underMouseNonShared = 0;
00202 linkPressed = false;
00203 useSlowRepaints = false;
00204 tabMovePending = false;
00205 lastTabbingDirection = true;
00206 pseudoFocusNode = PFNone;
00207 #ifndef KHTML_NO_SCROLLBARS
00208
00209
00210
00211
00212 #else
00213 vmode = QScrollView::AlwaysOff;
00214 hmode = QScrollView::AlwaysOff;
00215 #endif
00216 #ifdef DEBUG_PIXEL
00217 timer.start();
00218 pixelbooth = 0;
00219 repaintbooth = 0;
00220 #endif
00221 scrollBarMoved = false;
00222 contentsMoving = false;
00223 ignoreWheelEvents = false;
00224 borderX = 30;
00225 borderY = 30;
00226 paged = false;
00227 clickX = -1;
00228 clickY = -1;
00229 prevMouseX = -1;
00230 prevMouseY = -1;
00231 clickCount = 0;
00232 isDoubleClick = false;
00233 scrollingSelf = false;
00234 delete postponed_autorepeat;
00235 postponed_autorepeat = NULL;
00236 layoutTimerId = 0;
00237 repaintTimerId = 0;
00238 scrollTimerId = 0;
00239 scrollSuspended = false;
00240 scrollSuspendPreActivate = false;
00241 complete = false;
00242 firstRelayout = true;
00243 needsFullRepaint = true;
00244 dirtyLayout = false;
00245 layoutSchedulingEnabled = true;
00246 painting = false;
00247 updateRegion = QRegion();
00248 m_dialogsAllowed = true;
00249 #ifndef KHTML_NO_CARET
00250 if (m_caretViewContext) {
00251 m_caretViewContext->caretMoved = false;
00252 m_caretViewContext->keyReleasePending = false;
00253 }
00254 #endif // KHTML_NO_CARET
00255 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00256 typeAheadActivated = false;
00257 #endif // KHTML_NO_TYPE_AHEAD_FIND
00258 accessKeysActivated = false;
00259 accessKeysPreActivate = false;
00260
00261
00262 KHTMLFactory::ref();
00263 accessKeysEnabled = KHTMLFactory::defaultHTMLSettings()->accessKeysEnabled();
00264 KHTMLFactory::deref();
00265
00266 emitCompletedAfterRepaint = CSNone;
00267 }
00268 void newScrollTimer(QWidget *view, int tid)
00269 {
00270
00271 view->killTimer(scrollTimerId);
00272 scrollTimerId = tid;
00273 scrollSuspended = false;
00274 }
00275 enum ScrollDirection { ScrollLeft, ScrollRight, ScrollUp, ScrollDown };
00276
00277 void adjustScroller(QWidget *view, ScrollDirection direction, ScrollDirection oppositedir)
00278 {
00279 static const struct { int msec, pixels; } timings [] = {
00280 {320,1}, {224,1}, {160,1}, {112,1}, {80,1}, {56,1}, {40,1},
00281 {28,1}, {20,1}, {20,2}, {20,3}, {20,4}, {20,6}, {20,8}, {0,0}
00282 };
00283 if (!scrollTimerId ||
00284 (static_cast<int>(scrollDirection) != direction &&
00285 (static_cast<int>(scrollDirection) != oppositedir || scrollSuspended))) {
00286 scrollTiming = 6;
00287 scrollBy = timings[scrollTiming].pixels;
00288 scrollDirection = direction;
00289 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00290 } else if (scrollDirection == direction &&
00291 timings[scrollTiming+1].msec && !scrollSuspended) {
00292 scrollBy = timings[++scrollTiming].pixels;
00293 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00294 } else if (scrollDirection == oppositedir) {
00295 if (scrollTiming) {
00296 scrollBy = timings[--scrollTiming].pixels;
00297 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00298 }
00299 }
00300 scrollSuspended = false;
00301 }
00302
00303 #ifndef KHTML_NO_CARET
00304
00307 CaretViewContext *caretViewContext() {
00308 if (!m_caretViewContext) m_caretViewContext = new CaretViewContext();
00309 return m_caretViewContext;
00310 }
00314 EditorContext *editorContext() {
00315 if (!m_editorContext) m_editorContext = new EditorContext();
00316 return m_editorContext;
00317 }
00318 #endif // KHTML_NO_CARET
00319
00320 #ifdef DEBUG_PIXEL
00321 QTime timer;
00322 unsigned int pixelbooth;
00323 unsigned int repaintbooth;
00324 #endif
00325
00326 QPainter *tp;
00327 QPixmap *paintBuffer;
00328 QPixmap *vertPaintBuffer;
00329 NodeImpl *underMouse;
00330 NodeImpl *underMouseNonShared;
00331
00332 bool tabMovePending:1;
00333 bool lastTabbingDirection:1;
00334 PseudoFocusNodes pseudoFocusNode:2;
00335 bool scrollBarMoved:1;
00336 bool contentsMoving:1;
00337
00338 QScrollView::ScrollBarMode vmode;
00339 QScrollView::ScrollBarMode hmode;
00340 bool prevScrollbarVisible:1;
00341 bool linkPressed:1;
00342 bool useSlowRepaints:1;
00343 bool ignoreWheelEvents:1;
00344
00345 int borderX, borderY;
00346 KSimpleConfig *formCompletions;
00347
00348 bool paged;
00349
00350 int clickX, clickY, clickCount;
00351 bool isDoubleClick;
00352
00353 int prevMouseX, prevMouseY;
00354 bool scrollingSelf;
00355 int layoutTimerId;
00356 QKeyEvent* postponed_autorepeat;
00357
00358 int repaintTimerId;
00359 int scrollTimerId;
00360 int scrollTiming;
00361 int scrollBy;
00362 ScrollDirection scrollDirection :2;
00363 bool scrollSuspended :1;
00364 bool scrollSuspendPreActivate :1;
00365 bool complete :1;
00366 bool firstRelayout :1;
00367 bool layoutSchedulingEnabled :1;
00368 bool needsFullRepaint :1;
00369 bool painting :1;
00370 bool possibleTripleClick :1;
00371 bool dirtyLayout :1;
00372 bool m_dialogsAllowed :1;
00373 QRegion updateRegion;
00374 KHTMLToolTip *tooltip;
00375 QPtrDict<QWidget> visibleWidgets;
00376 #ifndef KHTML_NO_CARET
00377 CaretViewContext *m_caretViewContext;
00378 EditorContext *m_editorContext;
00379 #endif // KHTML_NO_CARET
00380 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00381 QString findString;
00382 QTimer timer;
00383 bool findLinksOnly;
00384 bool typeAheadActivated;
00385 #endif // KHTML_NO_TYPE_AHEAD_FIND
00386 bool accessKeysEnabled;
00387 bool accessKeysActivated;
00388 bool accessKeysPreActivate;
00389 CompletedState emitCompletedAfterRepaint;
00390
00391 QWidget* cursor_icon_widget;
00392
00393
00394 short m_mouseScroll_byX;
00395 short m_mouseScroll_byY;
00396 QTimer *m_mouseScrollTimer;
00397 QWidget *m_mouseScrollIndicator;
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 }
00507
00508 KHTMLView::~KHTMLView()
00509 {
00510 closeChildDialogs();
00511 if (m_part)
00512 {
00513
00514
00515 DOM::DocumentImpl *doc = m_part->xmlDocImpl();
00516 if (doc)
00517 doc->detach();
00518 }
00519 delete d; d = 0;
00520 }
00521
00522 void KHTMLView::init()
00523 {
00524 if(!d->paintBuffer) d->paintBuffer = new QPixmap(PAINT_BUFFER_HEIGHT, PAINT_BUFFER_HEIGHT);
00525 if(!d->vertPaintBuffer)
00526 d->vertPaintBuffer = new QPixmap(10, PAINT_BUFFER_HEIGHT);
00527 if(!d->tp) d->tp = new QPainter();
00528
00529 setFocusPolicy(QWidget::StrongFocus);
00530 viewport()->setFocusProxy(this);
00531
00532 _marginWidth = -1;
00533 _marginHeight = -1;
00534 _width = 0;
00535 _height = 0;
00536
00537 installEventFilter(this);
00538
00539 setAcceptDrops(true);
00540 QSize s = viewportSize(4095, 4095);
00541 resizeContents(s.width(), s.height());
00542 }
00543
00544 void KHTMLView::clear()
00545 {
00546
00547 setStaticBackground(true);
00548 #ifndef KHTML_NO_CARET
00549 if (!m_part->isCaretMode() && !m_part->isEditable()) caretOff();
00550 #endif
00551
00552 #ifndef KHTML_NO_TYPE_AHEAD_FIND
00553 if( d->typeAheadActivated )
00554 findTimeout();
00555 #endif
00556 if (d->accessKeysEnabled && d->accessKeysActivated)
00557 accessKeysTimeout();
00558 viewport()->unsetCursor();
00559 if ( d->cursor_icon_widget )
00560 d->cursor_icon_widget->hide();
00561 d->reset();
00562 killTimers();
00563 emit cleared();
00564
00565 QScrollView::setHScrollBarMode(d->hmode);
00566 QScrollView::setVScrollBarMode(d->vmode);
00567 verticalScrollBar()->setEnabled( false );
00568 horizontalScrollBar()->setEnabled( false );
00569 }
00570
00571 void KHTMLView::hideEvent(QHideEvent* e)
00572 {
00573 QScrollView::hideEvent(e);
00574 }
00575
00576 void KHTMLView::showEvent(QShowEvent* e)
00577 {
00578 QScrollView::showEvent(e);
00579 }
00580
00581 void KHTMLView::resizeEvent (QResizeEvent* e)
00582 {
00583 int dw = e->oldSize().width() - e->size().width();
00584 int dh = e->oldSize().height() - e->size().height();
00585
00586
00587
00588 dw = dw>0 ? kMax(0, contentsWidth()-dw) : contentsWidth();
00589 dh = dh>0 ? kMax(0, contentsHeight()-dh) : contentsHeight();
00590
00591 resizeContents(dw, dh);
00592
00593 QScrollView::resizeEvent(e);
00594
00595 if ( m_part && m_part->xmlDocImpl() )
00596 m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false );
00597 }
00598
00599 void KHTMLView::viewportResizeEvent (QResizeEvent* e)
00600 {
00601 QScrollView::viewportResizeEvent(e);
00602
00603
00604
00605
00606 if (d->layoutSchedulingEnabled)
00607 layout();
00608 #ifndef KHTML_NO_CARET
00609 else {
00610 hideCaret();
00611 recalcAndStoreCaretPos();
00612 showCaret();
00613 }
00614 #endif
00615
00616 KApplication::sendPostedEvents(viewport(), QEvent::Paint);
00617 }
00618
00619
00620 void KHTMLView::drawContents( QPainter*)
00621 {
00622 }
00623
00624 void KHTMLView::drawContents( QPainter *p, int ex, int ey, int ew, int eh )
00625 {
00626 #ifdef DEBUG_PIXEL
00627
00628 if ( d->timer.elapsed() > 5000 ) {
00629 qDebug( "drawed %d pixels in %d repaints the last %d milliseconds",
00630 d->pixelbooth, d->repaintbooth, d->timer.elapsed() );
00631 d->timer.restart();
00632 d->pixelbooth = 0;
00633 d->repaintbooth = 0;
00634 }
00635 d->pixelbooth += ew*eh;
00636 d->repaintbooth++;
00637 #endif
00638
00639
00640 if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
00641 p->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00642 return;
00643 } else if ( d->complete && static_cast<RenderCanvas*>(m_part->xmlDocImpl()->renderer())->needsLayout() ) {
00644
00645 unscheduleRelayout();
00646 layout();
00647 }
00648
00649 if (d->painting) {
00650 kdDebug( 6000 ) << "WARNING: drawContents reentered! " << endl;
00651 return;
00652 }
00653 d->painting = true;
00654
00655 QPoint pt = contentsToViewport(QPoint(ex, ey));
00656 QRegion cr = QRect(pt.x(), pt.y(), ew, eh);
00657
00658
00659 for (QPtrDictIterator<QWidget> it(d->visibleWidgets); it.current(); ++it) {
00660 QWidget *w = it.current();
00661 RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
00662 if (w && rw && !rw->isKHTMLWidget()) {
00663 int x, y;
00664 rw->absolutePosition(x, y);
00665 contentsToViewport(x, y, x, y);
00666 int pbx = rw->borderLeft()+rw->paddingLeft();
00667 int pby = rw->borderTop()+rw->paddingTop();
00668 QRect g = QRect(x+pbx, y+pby,
00669 rw->width()-pbx-rw->borderRight()-rw->paddingRight(),
00670 rw->height()-pby-rw->borderBottom()-rw->paddingBottom());
00671 if ( !rw->isFrame() && ((g.top() > pt.y()+eh) || (g.bottom() <= pt.y()) ||
00672 (g.right() <= pt.x()) || (g.left() > pt.x()+ew) ))
00673 continue;
00674 RenderLayer* rl = rw->needsMask() ? rw->enclosingStackingContext() : 0;
00675 QRegion mask = rl ? rl->getMask() : QRegion();
00676 if (!mask.isNull()) {
00677 QPoint o(0,0);
00678 o = contentsToViewport(o);
00679 mask.translate(o.x(),o.y());
00680 mask = mask.intersect( QRect(g.x(),g.y(),g.width(),g.height()) );
00681 cr -= mask;
00682 } else {
00683 cr -= g;
00684 }
00685 }
00686 }
00687
00688 #if 0
00689
00690
00691 if (cr.isEmpty()) {
00692 d->painting = false;
00693 return;
00694 }
00695 #endif
00696
00697 #ifndef DEBUG_NO_PAINT_BUFFER
00698 p->setClipRegion(cr);
00699
00700 if (eh > PAINT_BUFFER_HEIGHT && ew <= 10) {
00701 if ( d->vertPaintBuffer->height() < visibleHeight() )
00702 d->vertPaintBuffer->resize(10, visibleHeight());
00703 d->tp->begin(d->vertPaintBuffer);
00704 d->tp->translate(-ex, -ey);
00705 d->tp->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00706 m_part->xmlDocImpl()->renderer()->layer()->paint(d->tp, QRect(ex, ey, ew, eh));
00707 d->tp->end();
00708 p->drawPixmap(ex, ey, *d->vertPaintBuffer, 0, 0, ew, eh);
00709 }
00710 else {
00711 if ( d->paintBuffer->width() < visibleWidth() )
00712 d->paintBuffer->resize(visibleWidth(),PAINT_BUFFER_HEIGHT);
00713
00714 int py=0;
00715 while (py < eh) {
00716 int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;
00717 d->tp->begin(d->paintBuffer);
00718 d->tp->translate(-ex, -ey-py);
00719 d->tp->fillRect(ex, ey+py, ew, ph, palette().active().brush(QColorGroup::Base));
00720 m_part->xmlDocImpl()->renderer()->layer()->paint(d->tp, QRect(ex, ey+py, ew, ph));
00721 d->tp->end();
00722
00723 p->drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph);
00724 py += PAINT_BUFFER_HEIGHT;
00725 }
00726 }
00727 #else // !DEBUG_NO_PAINT_BUFFER
00728 static int cnt=0;
00729 ex = contentsX(); ey = contentsY();
00730 ew = visibleWidth(); eh = visibleHeight();
00731 QRect pr(ex,ey,ew,eh);
00732 kdDebug() << "[" << ++cnt << "]" << " clip region: " << pr << endl;
00733
00734
00735 p->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00736 m_part->xmlDocImpl()->renderer()->layer()->paint(p, pr);
00737 #endif // DEBUG_NO_PAINT_BUFFER
00738
00739 #ifndef KHTML_NO_CARET
00740 if (d->m_caretViewContext && d->m_caretViewContext->visible) {
00741 QRect pos(d->m_caretViewContext->x, d->m_caretViewContext->y,
00742 d->m_caretViewContext->width, d->m_caretViewContext->height);
00743 if (pos.intersects(QRect(ex, ey, ew, eh))) {
00744 p->setRasterOp(XorROP);
00745 p->setPen(white);
00746 if (pos.width() == 1)
00747 p->drawLine(pos.topLeft(), pos.bottomRight());
00748 else {
00749 p->fillRect(pos, white);
00750 }
00751 }
00752 }
00753 #endif // KHTML_NO_CARET
00754
00755
00756
00757
00758 khtml::DrawContentsEvent event( p, ex, ey, ew, eh );
00759 QApplication::sendEvent( m_part, &event );
00760
00761 d->painting = false;
00762 }
00763
00764 void KHTMLView::setMarginWidth(int w)
00765 {
00766
00767 _marginWidth = w;
00768 }
00769
00770 void KHTMLView::setMarginHeight(int h)
00771 {
00772
00773 _marginHeight = h;
00774 }
00775
00776 void KHTMLView::layout()
00777 {
00778 if( m_part && m_part->xmlDocImpl() ) {
00779 DOM::DocumentImpl *document = m_part->xmlDocImpl();
00780
00781 khtml::RenderCanvas* canvas = static_cast<khtml::RenderCanvas *>(document->renderer());
00782 if ( !canvas ) return;
00783
00784 d->layoutSchedulingEnabled=false;
00785
00786
00787 RenderObject * ref = 0;
00788 RenderObject* root = document->documentElement() ? document->documentElement()->renderer() : 0;
00789
00790 if (document->isHTMLDocument()) {
00791 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
00792 if(body && body->renderer() && body->id() == ID_FRAMESET) {
00793 QScrollView::setVScrollBarMode(AlwaysOff);
00794 QScrollView::setHScrollBarMode(AlwaysOff);
00795 body->renderer()->setNeedsLayout(true);
00796
00797
00798
00799
00800 }
00801 else {
00802 if (!d->tooltip)
00803 d->tooltip = new KHTMLToolTip( this, d );
00804
00805 if (root)
00806 ref = (!body || root->style()->hidesOverflow()) ? root : body->renderer();
00807 }
00808 } else {
00809 ref = root;
00810 }
00811
00812 if (ref) {
00813 if( ref->style()->overflow() == OHIDDEN ) {
00814 if (d->vmode == Auto) QScrollView::setVScrollBarMode(AlwaysOff);
00815 if (d->hmode == Auto) QScrollView::setHScrollBarMode(AlwaysOff);
00816 } else {
00817 if (QScrollView::vScrollBarMode() == AlwaysOff) QScrollView::setVScrollBarMode(d->vmode);
00818 if (QScrollView::hScrollBarMode() == AlwaysOff) QScrollView::setHScrollBarMode(d->hmode);
00819 }
00820 }
00821 d->needsFullRepaint = d->firstRelayout;
00822 if (_height != visibleHeight() || _width != visibleWidth()) {;
00823 d->needsFullRepaint = true;
00824 _height = visibleHeight();
00825 _width = visibleWidth();
00826 }
00827
00828
00829 canvas->layout();
00830
00831 emit finishedLayout();
00832 if (d->firstRelayout) {
00833
00834
00835 d->firstRelayout = false;
00836 verticalScrollBar()->setEnabled( true );
00837 horizontalScrollBar()->setEnabled( true );
00838 }
00839 #if 0
00840 ElementImpl *listitem = m_part->xmlDocImpl()->getElementById("__test_element__");
00841 if (listitem) kdDebug(6000) << "after layout, before repaint" << endl;
00842 if (listitem) dumpLineBoxes(static_cast<RenderFlow *>(listitem->renderer()));
00843 #endif
00844 #ifndef KHTML_NO_CARET
00845 hideCaret();
00846 if ((m_part->isCaretMode() || m_part->isEditable())
00847 && !d->complete && d->m_caretViewContext
00848 && !d->m_caretViewContext->caretMoved) {
00849 initCaret();
00850 } else {
00851 recalcAndStoreCaretPos();
00852 showCaret();
00853 }
00854 #endif
00855 if (d->accessKeysEnabled && d->accessKeysActivated) {
00856 emit hideAccessKeys();
00857 displayAccessKeys();
00858 }
00859
00860 }
00861 else
00862 _width = visibleWidth();
00863
00864 killTimer(d->layoutTimerId);
00865 d->layoutTimerId = 0;
00866 d->layoutSchedulingEnabled=true;
00867 }
00868
00869 void KHTMLView::closeChildDialogs()
00870 {
00871 QObjectList *dlgs = queryList("QDialog");
00872 for (QObject *dlg = dlgs->first(); dlg; dlg = dlgs->next())
00873 {
00874 KDialogBase* dlgbase = dynamic_cast<KDialogBase *>( dlg );
00875 if ( dlgbase ) {
00876 if ( dlgbase->testWFlags( WShowModal ) ) {
00877 kdDebug(6000) << "closeChildDialogs: closing dialog " << dlgbase << endl;
00878
00879
00880 dlgbase->cancel();
00881 }
00882 }
00883 else
00884 {
00885 kdWarning() << "closeChildDialogs: not a KDialogBase! Don't use QDialogs in KDE! " << static_cast<QWidget*>(dlg) << endl;
00886 static_cast<QWidget*>(dlg)->hide();
00887 }
00888 }
00889 delete dlgs;
00890 d->m_dialogsAllowed = false;
00891 }
00892
00893 bool KHTMLView::dialogsAllowed() {
00894 bool allowed = d->m_dialogsAllowed;
00895 KHTMLPart* p = m_part->parentPart();
00896 if (p && p->view())
00897 allowed &= p->view()->dialogsAllowed();
00898 return allowed;
00899 }
00900
00901 void KHTMLView::closeEvent( QCloseEvent* ev )
00902 {
00903 closeChildDialogs();
00904 QScrollView::closeEvent( ev );
00905 }
00906
00907
00908
00909
00911
00912 void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse )
00913 {
00914 if (!m_part->xmlDocImpl()) return;
00915 if (d->possibleTripleClick && ( _mouse->button() & MouseButtonMask ) == LeftButton)
00916 {
00917 viewportMouseDoubleClickEvent( _mouse );
00918 return;
00919 }
00920
00921 int xm, ym;
00922 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
00923
00924
00925 d->isDoubleClick = false;
00926
00927 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MousePress );
00928 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
00929
00930
00931
00932 if ( (_mouse->button() == MidButton) &&
00933 !m_part->d->m_bOpenMiddleClick && !d->m_mouseScrollTimer &&
00934 mev.url.isNull() && (mev.innerNode.elementId() != ID_INPUT) ) {
00935 QPoint point = mapFromGlobal( _mouse->globalPos() );
00936
00937 d->m_mouseScroll_byX = 0;
00938 d->m_mouseScroll_byY = 0;
00939
00940 d->m_mouseScrollTimer = new QTimer( this );
00941 connect( d->m_mouseScrollTimer, SIGNAL(timeout()), this, SLOT(slotMouseScrollTimer()) );
00942
00943 if ( !d->m_mouseScrollIndicator ) {
00944 QPixmap pixmap, icon;
00945 pixmap.resize( 48, 48 );
00946 pixmap.fill( QColor( qRgba( 127, 127, 127, 127 ) ) );
00947
00948 QPainter p( &pixmap );
00949 icon = KGlobal::iconLoader()->loadIcon( "1uparrow", KIcon::Small );
00950 p.drawPixmap( 16, 0, icon );
00951 icon = KGlobal::iconLoader()->loadIcon( "1leftarrow", KIcon::Small );
00952 p.drawPixmap( 0, 16, icon );
00953 icon = KGlobal::iconLoader()->loadIcon( "1downarrow", KIcon::Small );
00954 p.drawPixmap( 16, 32,icon );
00955 icon = KGlobal::iconLoader()->loadIcon( "1rightarrow", KIcon::Small );
00956 p.drawPixmap( 32, 16, icon );
00957 p.drawEllipse( 23, 23, 2, 2 );
00958
00959 d->m_mouseScrollIndicator = new QWidget( this, 0 );
00960 d->m_mouseScrollIndicator->setFixedSize( 48, 48 );
00961 d->m_mouseScrollIndicator->setPaletteBackgroundPixmap( pixmap );
00962 }
00963 d->m_mouseScrollIndicator->move( point.x()-24, point.y()-24 );
00964
00965 bool hasHorBar = visibleWidth() < contentsWidth();
00966 bool hasVerBar = visibleHeight() < contentsHeight();
00967
00968 KConfig *config = KGlobal::config();
00969 KConfigGroupSaver saver( config, "HTML Settings" );
00970 if ( config->readBoolEntry( "ShowMouseScrollIndicator", true ) ) {
00971 d->m_mouseScrollIndicator->show();
00972 d->m_mouseScrollIndicator->unsetCursor();
00973
00974 QBitmap mask = d->m_mouseScrollIndicator->paletteBackgroundPixmap()->createHeuristicMask( true );
00975
00976 if ( hasHorBar && !hasVerBar ) {
00977 QBitmap bm( 16, 16, true );
00978 bitBlt( &mask, 16, 0, &bm, 0, 0, -1, -1 );
00979 bitBlt( &mask, 16, 32, &bm, 0, 0, -1, -1 );
00980 d->m_mouseScrollIndicator->setCursor( KCursor::SizeHorCursor );
00981 }
00982 else if ( !hasHorBar && hasVerBar ) {
00983 QBitmap bm( 16, 16, true );
00984 bitBlt( &mask, 0, 16, &bm, 0, 0, -1, -1 );
00985 bitBlt( &mask, 32, 16, &bm, 0, 0, -1, -1 );
00986 d->m_mouseScrollIndicator->setCursor( KCursor::SizeVerCursor );
00987 }
00988 else
00989 d->m_mouseScrollIndicator->setCursor( KCursor::SizeAllCursor );
00990
00991 d->m_mouseScrollIndicator->setMask( mask );
00992 }
00993 else {
00994 if ( hasHorBar && !hasVerBar )
00995 viewport()->setCursor( KCursor::SizeHorCursor );
00996 else if ( !hasHorBar && hasVerBar )
00997 viewport()->setCursor( KCursor::SizeVerCursor );
00998 else
00999 viewport()->setCursor( KCursor::SizeAllCursor );
01000 }
01001
01002 return;
01003 }
01004 else if ( d->m_mouseScrollTimer ) {
01005 delete d->m_mouseScrollTimer;
01006 d->m_mouseScrollTimer = 0;
01007
01008 if ( d->m_mouseScrollIndicator )
01009 d->m_mouseScrollIndicator->hide();
01010 }
01011
01012 d->clickCount = 1;
01013 d->clickX = xm;
01014 d->clickY = ym;
01015
01016 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01017 d->clickCount,_mouse,true,DOM::NodeImpl::MousePress);
01018
01019 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
01020 if (r && r->isWidget())
01021 _mouse->ignore();
01022
01023 if (!swallowEvent) {
01024 emit m_part->nodeActivated(mev.innerNode);
01025
01026 khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
01027 QApplication::sendEvent( m_part, &event );
01028
01029 }
01030 }
01031
01032 void KHTMLView::viewportMouseDoubleClickEvent( QMouseEvent *_mouse )
01033 {
01034 if(!m_part->xmlDocImpl()) return;
01035
01036 int xm, ym;
01037 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
01038
01039 kdDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym << endl;
01040
01041 d->isDoubleClick = true;
01042
01043 DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseDblClick );
01044 m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
01045
01046
01047
01048 if (d->clickCount > 0 &&
01049 QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
01050 d->clickCount++;
01051 else {
01052 d->clickCount = 1;
01053 d->clickX = xm;
01054 d->clickY = ym;
01055 }
01056 bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
01057 d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick);
01058
01059 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
01060 if (r && r->isWidget())
01061 _mouse->ignore();
01062
01063 if (!swallowEvent) {
01064 khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode, d->clickCount );
01065 QApplication::sendEvent( m_part, &event );
01066 }
01067
01068 d->possibleTripleClick=true;
01069 QTimer::singleShot(QApplication::doubleClickInterval(),this,SLOT(tripleClickTimeout()));
01070 }
01071
01072 void KHTMLView::tripleClickTimeout()
01073 {
01074 d->possibleTripleClick = false;
01075 d->clickCount = 0;
01076 }
01077
01078 static inline void forwardPeripheralEvent(khtml::RenderWidget* r, QMouseEvent* me, int x, int y)
01079 {
01080 int absx = 0;
01081 int absy = 0;
01082 r->absolutePosition(absx, absy);
01083 QPoint p(x-absx, y-absy);
01084 QMouseEvent fw(me->type(), p, me->button(), me->state());
01085 QWidget* w = r->widget();
01086 QScrollView* sc = ::qt_cast<QScrollView*>(w);
01087 if (sc && !::qt_cast<QListBox*>(w))
01088 static_cast<khtml::RenderWidget::ScrollViewEventPropagator*>(sc)->sendEvent(&fw);
01089 else if(w)
01090 static_cast<khtml::RenderWidget::EventPropagator*>(w)->sendEvent(&fw);
01091 }
01092
01093 void KHTMLView::viewportMouseMoveEvent( QMouseEvent * _mouse )
01094 {
01095 if ( d->m_mouseScrollTimer ) {
01096 QPoint point = mapFromGlobal( _mouse->globalPos() );
01097
01098 int deltaX = point.x() - d->m_mouseScrollIndicator->x() - 24;
01099 int deltaY = point.y() - d->m_mouseScrollIndicator->y() - 24;
01100
01101 (deltaX > 0) ? d->m_mouseScroll_byX = 1 : d->m_mouseScroll_byX = -1;
01102 (deltaY > 0) ? d->m_mouseScroll_byY = 1 : d->m_mouseScroll_byY = -1;
01103
01104 double adX = QABS(deltaX)/30.0;
01105 double adY = QABS(deltaY)/30.0;
01106
01107 d->m_mouseScroll_byX = kMax(kMin(d->m_mouseScroll_byX * int(adX*adX), SHRT_MAX), SHRT_MIN);
01108 d->m_mouseScroll_byY = kMax(kMin(d->m_mouseScroll_byY * int(adY*adY), SHRT_MAX), SHRT_MIN);
01109
01110 if (d->m_mouseScroll_byX == 0 && d->m_mouseScroll_byY == 0) {
01111 d->m_mouseScrollTimer->stop();
01112 }
01113 else if (!d->m_mouseScrollTimer->isActive()) {
01114 d->m_mouseScrollTimer->changeInterval( 20 );
01115 }
01116 }
01117
01118 if(!m_part->xmlDocImpl()) return;
01119
01120 int xm, ym;
01121 viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
01122
01123 DOM::NodeImpl::MouseEvent mev( _mouse->