Reviewed by Darin.
[WebKit-https.git] / WebCore / khtml / khtmlview.cpp
1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
4  *                     1999 Lars Knoll <knoll@kde.org>
5  *                     1999 Antti Koivisto <koivisto@kde.org>
6  *                     2000 Dirk Mueller <mueller@kde.org>
7  * Copyright (C) 2004 Apple Computer, Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24 #include "khtmlview.moc"
25
26 #include "khtmlview.h"
27
28 #include "khtml_part.h"
29 #include "khtml_events.h"
30
31 #include "html/html_documentimpl.h"
32 #include "html/html_inlineimpl.h"
33 #include "html/html_formimpl.h"
34 #include "rendering/render_arena.h"
35 #include "rendering/render_object.h"
36 #include "rendering/render_canvas.h"
37 #include "rendering/render_style.h"
38 #include "rendering/render_replaced.h"
39 #include "rendering/render_line.h"
40 #include "rendering/render_text.h"
41 #include "xml/dom_nodeimpl.h"
42 #include "xml/dom_selection.h"
43 #include "xml/dom2_eventsimpl.h"
44 #include "css/cssstyleselector.h"
45 #include "misc/htmlhashes.h"
46 #include "misc/helper.h"
47 #include "khtml_settings.h"
48 #include "khtml_printsettings.h"
49 #include "khtmlpart_p.h"
50
51 #include <kcursor.h>
52 #include <ksimpleconfig.h>
53 #include <kstandarddirs.h>
54 #include <kprinter.h>
55
56 #include <qtooltip.h>
57 #include <qpainter.h>
58 #include <qpaintdevicemetrics.h>
59 #include <kapplication.h>
60
61 #include <kimageio.h>
62 #include <assert.h>
63 #include <kdebug.h>
64 #include <kurldrag.h>
65 #include <qobjectlist.h>
66
67 #if APPLE_CHANGES
68 #include "KWQAccObjectCache.h"
69 #endif
70
71 #define PAINT_BUFFER_HEIGHT 128
72
73 //#define INSTRUMENT_LAYOUT_SCHEDULING 1
74
75 using namespace DOM;
76 using namespace khtml;
77 class KHTMLToolTip;
78
79 #ifndef QT_NO_TOOLTIP
80
81 class KHTMLToolTip : public QToolTip
82 {
83 public:
84     KHTMLToolTip(KHTMLView *view,  KHTMLViewPrivate* vp) : QToolTip(view->viewport())
85     {
86         m_view = view;
87         m_viewprivate = vp;
88     };
89
90 protected:
91     virtual void maybeTip(const QPoint &);
92
93 private:
94
95     KHTMLView *m_view;
96     KHTMLViewPrivate* m_viewprivate;
97 };
98
99 #endif
100
101 class KHTMLViewPrivate {
102     friend class KHTMLToolTip;
103 public:
104     KHTMLViewPrivate()
105     {
106         repaintRects = 0;
107         underMouse = 0;
108         reset();
109 #if !APPLE_CHANGES
110         tp=0;
111         paintBuffer=0;
112         formCompletions=0;
113 #endif
114         layoutTimerId = 0;
115         allDataReceivedWhenTimerSet = false;
116         mousePressed = false;
117 #ifndef QT_NO_TOOLTIP
118         tooltip = 0;
119 #endif
120         doFullRepaint = true;
121         isTransparent = false;
122 #if APPLE_CHANGES
123         vmode = hmode = QScrollView::Auto;
124         firstLayout = true;
125         needToInitScrollBars = true;
126 #else
127         prevScrollbarVisible = true;
128 #endif
129     }
130     ~KHTMLViewPrivate()
131     {
132 #if !APPLE_CHANGES
133         delete formCompletions;
134         delete tp; tp = 0;
135         delete paintBuffer; paintBuffer =0;
136 #endif
137         
138         if (underMouse)
139             underMouse->deref();
140 #ifndef QT_NO_TOOLTIP
141         delete tooltip;
142 #endif
143         delete repaintRects;
144     }
145     void reset()
146     {
147         if (underMouse)
148             underMouse->deref();
149         underMouse = 0;
150         linkPressed = false;
151         useSlowRepaints = false;
152         originalNode = 0;
153         dragTarget = 0;
154         borderTouched = false;
155 #if !APPLE_CHANGES
156 #ifndef KHTML_NO_SCROLLBARS
157         vmode = QScrollView::Auto;
158         hmode = QScrollView::Auto;
159 #else
160         vmode = QScrollView::AlwaysOff;
161         hmode = QScrollView::AlwaysOff;
162 #endif
163 #endif
164         scrollBarMoved = false;
165         ignoreWheelEvents = false;
166         borderX = 30;
167         borderY = 30;
168         clickX = -1;
169         clickY = -1;
170         prevMouseX = -1;
171         prevMouseY = -1;
172         clickCount = 0;
173         isDoubleClick = false;
174         scrollingSelf = false;
175         layoutTimerId = 0;
176         allDataReceivedWhenTimerSet = false;
177         mousePressed = false;
178         doFullRepaint = true;
179         layoutSchedulingEnabled = true;
180         layoutSuppressed = false;
181         layoutCount = 0;
182 #if APPLE_CHANGES
183         firstLayout = true;
184 #endif
185         if (repaintRects)
186             repaintRects->clear();
187     }
188
189 #if !APPLE_CHANGES
190     QPainter *tp;
191     QPixmap  *paintBuffer;
192 #endif
193     NodeImpl *underMouse;
194
195     // the node that was selected when enter was pressed
196     NodeImpl *originalNode;
197
198     bool borderTouched:1;
199     bool borderStart:1;
200     bool scrollBarMoved:1;
201     bool doFullRepaint:1;
202     
203     QScrollView::ScrollBarMode vmode;
204     QScrollView::ScrollBarMode hmode;
205 #if !APPLE_CHANGES
206     bool prevScrollbarVisible;
207 #endif
208     bool linkPressed;
209     bool useSlowRepaints;
210     bool ignoreWheelEvents;
211
212     int borderX, borderY;
213 #if !APPLE_CHANGES
214     KSimpleConfig *formCompletions;
215 #endif
216
217     int clickX, clickY, clickCount;
218     bool isDoubleClick;
219
220     int prevMouseX, prevMouseY;
221     bool scrollingSelf;
222     int layoutTimerId;
223     bool allDataReceivedWhenTimerSet;
224     
225     bool layoutSchedulingEnabled;
226     bool layoutSuppressed;
227     int layoutCount;
228
229 #if APPLE_CHANGES
230     bool firstLayout;
231     bool needToInitScrollBars;
232 #endif
233     bool mousePressed;
234     bool isTransparent;
235 #ifndef QT_NO_TOOLTIP
236     KHTMLToolTip *tooltip;
237 #endif
238     
239     // Used by objects during layout to communicate repaints that need to take place only
240     // after all layout has been completed.
241     QPtrList<RenderObject::RepaintInfo>* repaintRects;
242     
243     Node dragTarget;
244 };
245
246 #ifndef QT_NO_TOOLTIP
247
248 void KHTMLToolTip::maybeTip(const QPoint& /*p*/)
249 {
250     DOM::NodeImpl *node = m_viewprivate->underMouse;
251     while ( node ) {
252         if ( node->isElementNode() ) {
253             AtomicString s = static_cast<DOM::ElementImpl*>( node )->getAttribute(ATTR_TITLE);
254             if (!s.isEmpty()) {
255                 QRect r( m_view->contentsToViewport( node->getRect().topLeft() ), node->getRect().size() );
256                 tip( r,  s.string() );
257             }
258             break;
259         }
260         node = node->parentNode();
261     }
262 }
263 #endif
264
265 KHTMLView::KHTMLView( KHTMLPart *part, QWidget *parent, const char *name)
266     : QScrollView( parent, name, WResizeNoErase | WRepaintNoErase | WPaintUnclipped ),
267       _refCount(1)
268 {
269     m_medium = "screen";
270
271     m_part = part;
272 #if APPLE_CHANGES
273     m_part->ref();
274 #endif
275     d = new KHTMLViewPrivate;
276
277 #if !APPLE_CHANGES
278     QScrollView::setVScrollBarMode(d->vmode);
279     QScrollView::setHScrollBarMode(d->hmode);
280 #endif
281     
282     connect(kapp, SIGNAL(kdisplayPaletteChanged()), this, SLOT(slotPaletteChanged()));
283     connect(this, SIGNAL(contentsMoving(int, int)), this, SLOT(slotScrollBarMoved()));
284
285     // initialize QScrollview
286     enableClipper(true);
287     viewport()->setMouseTracking(true);
288     viewport()->setBackgroundMode(NoBackground);
289
290     KImageIO::registerFormats();
291
292 #ifndef QT_NO_TOOLTIP
293     d->tooltip = new KHTMLToolTip( this, d );
294 #endif
295
296     init();
297
298     viewport()->show();
299 }
300
301 KHTMLView::~KHTMLView()
302 {
303 #if APPLE_CHANGES
304     resetScrollBars();
305 #endif
306
307     assert(_refCount == 0);
308
309     if (m_part)
310     {
311         //WABA: Is this Ok? Do I need to deref it as well?
312         //Does this need to be done somewhere else?
313         DOM::DocumentImpl *doc = m_part->xmlDocImpl();
314         if (doc)
315             doc->detach();
316
317 #if APPLE_CHANGES
318         m_part->deref();
319 #endif
320     }
321
322     delete d; d = 0;
323 }
324
325 void KHTMLView::clearPart()
326 {
327     if (m_part){
328         m_part->deref();
329         m_part = 0;
330     }
331 }
332
333 #if APPLE_CHANGES
334 void KHTMLView::resetScrollBars()
335 {
336     // Reset the document's scrollbars back to our defaults before we yield the floor.
337     d->firstLayout = true;
338     suppressScrollBars(true);
339     QScrollView::setVScrollBarMode(d->vmode);
340     QScrollView::setHScrollBarMode(d->hmode);
341     suppressScrollBars(false);
342 }
343 #endif
344
345 void KHTMLView::init()
346 {
347 #if !APPLE_CHANGES
348     if(!d->paintBuffer) d->paintBuffer = new QPixmap(PAINT_BUFFER_HEIGHT, PAINT_BUFFER_HEIGHT);
349     if(!d->tp) d->tp = new QPainter();
350 #endif
351
352     setFocusPolicy(QWidget::StrongFocus);
353     viewport()->setFocusPolicy( QWidget::WheelFocus );
354     viewport()->setFocusProxy(this);
355
356     _marginWidth = -1; // undefined
357     _marginHeight = -1;
358     _width = 0;
359     _height = 0;
360
361     setAcceptDrops(true);
362     
363 #if !APPLE_CHANGES
364     resizeContents(visibleWidth(), visibleHeight());
365 #endif
366 }
367
368 void KHTMLView::clear()
369 {
370 //    viewport()->erase();
371
372     setStaticBackground(false);
373     
374     m_part->clearSelection();
375
376     d->reset();
377     killTimers();
378     emit cleared();
379
380 #if APPLE_CHANGES
381     suppressScrollBars(true);
382 #else
383     QScrollView::setHScrollBarMode(d->hmode);
384     if (d->vmode==Auto)
385         QScrollView::setVScrollBarMode(d->prevScrollbarVisible?AlwaysOn:Auto);
386     else
387         QScrollView::setVScrollBarMode(d->vmode);
388     resizeContents(visibleWidth(), visibleHeight());
389 #endif
390 }
391
392 void KHTMLView::hideEvent(QHideEvent* e)
393 {
394 //    viewport()->setBackgroundMode(PaletteBase);
395     QScrollView::hideEvent(e);
396 }
397
398 void KHTMLView::showEvent(QShowEvent* e)
399 {
400 //    viewport()->setBackgroundMode(NoBackground);
401     QScrollView::showEvent(e);
402 }
403
404 void KHTMLView::resizeEvent (QResizeEvent* e)
405 {
406     QScrollView::resizeEvent(e);
407
408 #if !APPLE_CHANGES
409     int w = visibleWidth();
410     int h = visibleHeight();
411
412     layout();
413
414     //  this is to make sure we get the right width even if the scrolbar has dissappeared
415     // due to the size change.
416     if(visibleHeight() != h || visibleWidth() != w)
417         layout();
418 #endif
419     if ( m_part && m_part->xmlDocImpl() )
420         m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false );
421
422     KApplication::sendPostedEvents(viewport(), QEvent::Paint);
423 }
424
425 #if APPLE_CHANGES
426 void KHTMLView::initScrollBars()
427 {
428     if (!d->needToInitScrollBars)
429         return;
430     d->needToInitScrollBars = false;
431     setScrollBarsMode(hScrollBarMode());
432 }
433 #endif
434
435 #if !APPLE_CHANGES
436
437 // this is to get rid of a compiler virtual overload mismatch warning. do not remove
438 void KHTMLView::drawContents( QPainter*)
439 {
440 }
441
442 void KHTMLView::drawContents( QPainter *p, int ex, int ey, int ew, int eh )
443 {
444     //kdDebug( 6000 ) << "drawContents x=" << ex << ",y=" << ey << ",w=" << ew << ",h=" << eh << endl;
445     if(!m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
446         p->fillRect(ex, ey, ew, eh, palette().normal().brush(QColorGroup::Base));
447         return;
448     }
449     if ( d->paintBuffer->width() < visibleWidth() )
450         d->paintBuffer->resize(visibleWidth(),PAINT_BUFFER_HEIGHT);
451
452     int py=0;
453     while (py < eh) {
454         int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;
455         d->tp->begin(d->paintBuffer);
456         d->tp->translate(-ex, -ey-py);
457         d->tp->fillRect(ex, ey+py, ew, ph, palette().normal().brush(QColorGroup::Base));
458         m_part->xmlDocImpl()->renderer()->print(d->tp, ex, ey+py, ew, ph, 0, 0);
459 #ifdef BOX_DEBUG
460         if (m_part->xmlDocImpl()->focusNode())
461         {
462             d->tp->setBrush(Qt::NoBrush);
463             d->tp->drawRect(m_part->xmlDocImpl()->focusNode()->getRect());
464         }
465 #endif
466         d->tp->end();
467
468         p->drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph);
469         py += PAINT_BUFFER_HEIGHT;
470     }
471
472     // EDIT FIXME: KDE needs to draw the caret here.
473
474     khtml::DrawContentsEvent event( p, ex, ey, ew, eh );
475     QApplication::sendEvent( m_part, &event );
476
477 }
478
479 #endif // !APPLE_CHANGES
480
481 void KHTMLView::setMarginWidth(int w)
482 {
483     // make it update the rendering area when set
484     _marginWidth = w;
485 }
486
487 void KHTMLView::setMarginHeight(int h)
488 {
489     // make it update the rendering area when set
490     _marginHeight = h;
491 }
492
493
494 void KHTMLView::adjustViewSize()
495 {
496     if( m_part->xmlDocImpl() ) {
497         DOM::DocumentImpl *document = m_part->xmlDocImpl();
498
499         khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer());
500         if ( !root )
501             return;
502         
503         int docw = root->docWidth();
504         int doch = root->docHeight();
505     
506         resizeContents(docw, doch);
507     }
508 }
509
510 void KHTMLView::applyBodyScrollQuirk(khtml::RenderObject* o, ScrollBarMode& hMode, ScrollBarMode& vMode)
511 {
512     // Handle the overflow:hidden/scroll quirk for the body elements.  WinIE treats
513     // overflow:hidden and overflow:scroll on <body> as applying to the document's
514     // scrollbars.  The CSS2.1 draft has even added a sentence, "HTML UAs may apply overflow
515     // specified on the body or HTML elements to the viewport."  Since WinIE and Mozilla both
516     // do it, we will do it too for <body> elements.
517     switch(o->style()->overflow()) {
518         case OHIDDEN:
519             hMode = vMode = AlwaysOff;
520             break;
521         case OSCROLL:
522             hMode = vMode = AlwaysOn;
523             break;
524         case OAUTO:
525             hMode = vMode = Auto;
526             break;
527         default:
528             // Don't set it at all.
529             ;
530     }
531 }
532
533 bool KHTMLView::inLayout() const
534 {
535     return d->layoutSuppressed;
536 }
537
538 int KHTMLView::layoutCount() const
539 {
540     return d->layoutCount;
541 }
542
543 bool KHTMLView::needsFullRepaint() const
544 {
545     return d->doFullRepaint;
546 }
547
548 void KHTMLView::addRepaintInfo(RenderObject* o, const QRect& r)
549 {
550     if (!d->repaintRects) {
551         d->repaintRects = new QPtrList<RenderObject::RepaintInfo>;
552         d->repaintRects->setAutoDelete(true);
553     }
554     
555     d->repaintRects->append(new RenderObject::RepaintInfo(o, r));
556 }
557
558 void KHTMLView::layout()
559 {
560     if (d->layoutSuppressed)
561         return;
562     
563     d->layoutSchedulingEnabled=false;
564     killTimer(d->layoutTimerId);
565     d->layoutTimerId = 0;
566     d->allDataReceivedWhenTimerSet = false;
567
568     if (!m_part) {
569         // FIXME: Do we need to set _width here?
570         // FIXME: Should we set _height here too?
571         _width = visibleWidth();
572         return;
573     }
574
575     DOM::DocumentImpl* document = m_part->xmlDocImpl();
576     if (!document) {
577         // FIXME: Should we set _height here too?
578         _width = visibleWidth();
579         return;
580     }
581
582     // Always ensure our style info is up-to-date.  This can happen in situations where
583     // the layout beats any sort of style recalc update that needs to occur.
584     if (document->hasChangedChild())
585         document->recalcStyle();
586
587     khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas*>(document->renderer());
588     if (!root) {
589         // FIXME: Do we need to set _width or _height here?
590         return;
591     }
592
593     ScrollBarMode hMode = d->hmode;
594     ScrollBarMode vMode = d->vmode;
595     
596     if (document->isHTMLDocument()) {
597         NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
598         if (body && body->renderer()) {
599             if (body->id() == ID_FRAMESET) {
600                 body->renderer()->setNeedsLayout(true);
601                 vMode = AlwaysOff;
602                 hMode = AlwaysOff;
603             }
604             else if (body->id() == ID_BODY)
605                 applyBodyScrollQuirk(body->renderer(), hMode, vMode); // Only applies to HTML UAs, not to XML/XHTML UAs
606         }
607     }
608
609 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
610     if (d->firstLayout && !document->ownerElement())
611         printf("Elapsed time before first layout: %d\n", document->elapsedTime());
612 #endif
613
614     d->doFullRepaint = d->firstLayout || root->printingMode();
615     if (d->repaintRects)
616         d->repaintRects->clear();
617
618 #if APPLE_CHANGES
619     // Now set our scrollbar state for the layout.
620     ScrollBarMode currentHMode = hScrollBarMode();
621     ScrollBarMode currentVMode = vScrollBarMode();
622
623     if (d->firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
624         suppressScrollBars(true);
625         if (d->firstLayout) {
626             d->firstLayout = false;
627             
628             // Set the initial vMode to AlwaysOn if we're auto.
629             if (vMode == Auto)
630                 QScrollView::setVScrollBarMode(AlwaysOn); // This causes a vertical scrollbar to appear.
631             // Set the initial hMode to AlwaysOff if we're auto.
632             if (hMode == Auto)
633                 QScrollView::setHScrollBarMode(AlwaysOff); // This causes a horizontal scrollbar to disappear.
634         }
635         
636         if (hMode == vMode)
637             QScrollView::setScrollBarsMode(hMode);
638         else {
639             QScrollView::setHScrollBarMode(hMode);
640             QScrollView::setVScrollBarMode(vMode);
641         }
642
643         suppressScrollBars(false, true);
644     }
645 #else
646     QScrollView::setHScrollBarMode(hMode);
647     QScrollView::setVScrollBarMode(vMode);
648 #endif
649
650     int oldHeight = _height;
651     int oldWidth = _width;
652     
653     _height = visibleHeight();
654     _width = visibleWidth();
655
656     if (oldHeight != _height || oldWidth != _width)
657         d->doFullRepaint = true;
658     
659     RenderLayer* layer = root->layer();
660      
661     if (!d->doFullRepaint) {
662         layer->computeRepaintRects();
663         root->repaintObjectsBeforeLayout();
664     }
665
666     root->layout();
667
668     m_part->invalidateSelection();
669         
670     //kdDebug( 6000 ) << "TIME: layout() dt=" << qt.elapsed() << endl;
671    
672     d->layoutSchedulingEnabled=true;
673     d->layoutSuppressed = false;
674
675     if (!root->printingMode())
676         resizeContents(layer->width(), layer->height());
677
678     // Now update the positions of all layers.
679     layer->updateLayerPositions(d->doFullRepaint);
680
681 #if APPLE_CHANGES
682     // We update our widget positions right after doing a layout.
683     root->updateWidgetPositions();
684 #endif
685     
686     if (d->repaintRects && !d->repaintRects->isEmpty()) {
687         // FIXME: Could optimize this and have objects removed from this list
688         // if they ever do full repaints.
689         RenderObject::RepaintInfo* r;
690         QPtrListIterator<RenderObject::RepaintInfo> it(*d->repaintRects);
691         for ( ; (r = it.current()); ++it)
692             r->m_object->repaintRectangle(r->m_repaintRect);
693         d->repaintRects->clear();
694     }
695     
696     d->layoutCount++;
697 #if APPLE_CHANGES
698     if (KWQAccObjectCache::accessibilityEnabled())
699         root->document()->getOrCreateAccObjectCache()->postNotification(root, "AXLayoutComplete");
700 #endif
701
702     if (root->needsLayout()) {
703         //qDebug("needs layout, delaying repaint");
704         scheduleRelayout();
705         return;
706     }
707     setStaticBackground(d->useSlowRepaints);
708 }
709
710 //
711 // Event Handling
712 //
713 /////////////////
714
715 void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse )
716 {
717     if(!m_part->xmlDocImpl()) return;
718
719     int xm, ym;
720     viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
721
722     //kdDebug( 6000 ) << "\nmousePressEvent: x=" << xm << ", y=" << ym << endl;
723
724     d->isDoubleClick = false;
725     d->mousePressed = true;
726
727     DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MousePress );
728     m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
729
730 #if !APPLE_CHANGES
731     if (d->clickCount > 0 &&
732         QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
733         d->clickCount++;
734     else {
735         d->clickCount = 1;
736         d->clickX = xm;
737         d->clickY = ym;
738     }
739 #else
740     if (KWQ(m_part)->passSubframeEventToSubframe(mev))
741         return;
742
743     d->clickX = xm;
744     d->clickY = ym;
745     d->clickCount = _mouse->clickCount();
746 #endif    
747
748     bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),true,
749                                            d->clickCount,_mouse,true,DOM::NodeImpl::MousePress);
750
751     if (!swallowEvent) {
752         khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
753         QApplication::sendEvent( m_part, &event );
754 #if APPLE_CHANGES
755         // Many AK widgets run their own event loops and consume events while the mouse is down.
756         // When they finish, currentEvent is the mouseUp that they exited on.  We need to update
757         // the khtml state with this mouseUp, which khtml never saw.
758         // If this event isn't a mouseUp, we assume that the mouseUp will be coming later.  There
759         // is a hole here if the widget consumes the mouseUp and subsequent events.
760         if (KWQ(m_part)->lastEventIsMouseUp()) {
761             d->mousePressed = false;
762         }
763 #endif        
764         emit m_part->nodeActivated(mev.innerNode);
765     }
766 }
767
768 void KHTMLView::viewportMouseDoubleClickEvent( QMouseEvent *_mouse )
769 {
770     if(!m_part->xmlDocImpl()) return;
771
772     int xm, ym;
773     viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
774
775     //kdDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym << endl;
776
777     d->isDoubleClick = true;
778 #if APPLE_CHANGES
779     // We get this instead of a second mouse-up 
780     d->mousePressed = false;
781 #endif
782
783     DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseDblClick );
784     m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
785
786 #if APPLE_CHANGES
787     if (KWQ(m_part)->passSubframeEventToSubframe(mev))
788         return;
789
790     d->clickCount = _mouse->clickCount();
791     bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,mev.innerNode.handle(),true,
792                                            d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease);
793     
794     dispatchMouseEvent(EventImpl::CLICK_EVENT,mev.innerNode.handle(),true,
795                            d->clickCount,_mouse,true,DOM::NodeImpl::MouseRelease);
796
797     // Qt delivers a release event AND a double click event.
798     if (!swallowEvent) {
799         khtml::MouseReleaseEvent event1( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
800         QApplication::sendEvent( m_part, &event1 );
801
802         khtml::MouseDoubleClickEvent event2( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
803         QApplication::sendEvent( m_part, &event2 );
804     }
805
806 #else
807     // We do the same thing as viewportMousePressEvent() here, since the DOM does not treat
808     // single and double-click events as separate (only the detail, i.e. number of clicks differs)
809     // In other words an even detail value for a mouse click event means a double click, and an
810     // odd detail value means a single click
811     bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),true,
812                                            d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick);
813
814     if (!swallowEvent) {
815         khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
816         QApplication::sendEvent( m_part, &event );
817
818         // ###
819         //if ( url.length() )
820         //emit doubleClick( url.string(), _mouse->button() );
821     }
822 #endif    
823 }
824
825 static bool isSubmitImage(DOM::NodeImpl *node)
826 {
827     return node
828         && node->isHTMLElement()
829         && node->id() == ID_INPUT
830         && static_cast<HTMLInputElementImpl*>(node)->inputType() == HTMLInputElementImpl::IMAGE;
831 }
832
833 void KHTMLView::viewportMouseMoveEvent( QMouseEvent * _mouse )
834 {
835     // in Radar 3703768 we saw frequent crashes apparently due to the
836     // part being null here, which seems impossible, so check for nil
837     // but also assert so that we can try to figure this out in debug
838     // builds, if it happens.
839     assert(m_part);
840     if(!m_part || !m_part->xmlDocImpl()) return;
841
842     int xm, ym;
843     viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
844
845     // Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent.
846     // This means that :hover and :active freeze in the state they were in when the mouse
847     // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down.
848     DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseMove );
849     m_part->xmlDocImpl()->prepareMouseEvent( d->mousePressed, xm, ym, &mev );
850 #if APPLE_CHANGES
851     if (KWQ(m_part)->passSubframeEventToSubframe(mev))
852         return;
853 #endif
854
855     bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,mev.innerNode.handle(),false,
856                                            0,_mouse,true,DOM::NodeImpl::MouseMove);
857
858 #if !APPLE_CHANGES
859     if (d->clickCount > 0 &&
860         QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() > QApplication::startDragDistance()) {
861         d->clickCount = 0;  // moving the mouse outside the threshold invalidates the click
862     }
863 #endif
864
865     // execute the scheduled script. This is to make sure the mouseover events come after the mouseout events
866     m_part->executeScheduledScript();
867
868     khtml::RenderStyle* style = (mev.innerNode.handle() && mev.innerNode.handle()->renderer() &&
869                                  mev.innerNode.handle()->renderer()->style()) ? mev.innerNode.handle()->renderer()->style() : 0;
870     QCursor c;
871     if (style && style->cursor() == CURSOR_AUTO && style->cursorImage()
872         && !(style->cursorImage()->pixmap().isNull())) {
873         /* First of all it works: Check out http://www.iam.unibe.ch/~schlpbch/cursor.html
874          *
875          * But, I don't know what exactly we have to do here: rescale to 32*32, change to monochrome..
876          */
877         //kdDebug( 6000 ) << "using custom cursor" << endl;
878         const QPixmap p = style->cursorImage()->pixmap();
879         // ### fix
880         c = QCursor(p);
881     }
882
883     switch ( style ? style->cursor() : CURSOR_AUTO) {
884     case CURSOR_AUTO:
885         if ( d->mousePressed && m_part->hasSelection() )
886             // during selection, use an IBeam no matter what we're over
887             c = KCursor::ibeamCursor();
888         else if ( (!mev.url.isNull() || isSubmitImage(mev.innerNode.handle()))
889                   && m_part->settings()->changeCursor() )
890             c = m_part->urlCursor();
891         else if ( !mev.innerNode.isNull()
892                   && (mev.innerNode.nodeType() == Node::TEXT_NODE
893                       || mev.innerNode.nodeType() == Node::CDATA_SECTION_NODE
894                       || (mev.innerNode.isContentEditable())))
895             c = KCursor::ibeamCursor();
896         break;
897     case CURSOR_CROSS:
898         c = KCursor::crossCursor();
899         break;
900     case CURSOR_POINTER:
901         c = m_part->urlCursor();
902         break;
903     case CURSOR_MOVE:
904         c = KCursor::sizeAllCursor();
905         break;
906     case CURSOR_E_RESIZE:
907 #if APPLE_CHANGES
908         c = KCursor::eastResizeCursor();
909         break;
910 #endif
911     case CURSOR_W_RESIZE:
912 #if APPLE_CHANGES
913         c = KCursor::westResizeCursor();
914 #else
915         c = KCursor::sizeHorCursor();
916 #endif
917         break;
918     case CURSOR_N_RESIZE:
919 #if APPLE_CHANGES
920         c = KCursor::northResizeCursor();
921         break;
922 #endif
923     case CURSOR_S_RESIZE:
924 #if APPLE_CHANGES
925         c = KCursor::southResizeCursor();
926 #else
927         c = KCursor::sizeVerCursor();
928 #endif
929         break;
930     case CURSOR_NE_RESIZE:
931 #if APPLE_CHANGES
932         c = KCursor::northEastResizeCursor();
933         break;
934 #endif
935     case CURSOR_SW_RESIZE:
936 #if APPLE_CHANGES
937         c = KCursor::southWestResizeCursor();
938 #else
939         c = KCursor::sizeBDiagCursor();
940 #endif
941         break;
942     case CURSOR_NW_RESIZE:
943 #if APPLE_CHANGES
944         c = KCursor::northWestResizeCursor();
945         break;
946 #endif
947     case CURSOR_SE_RESIZE:
948 #if APPLE_CHANGES
949         c = KCursor::southEastResizeCursor();
950 #else
951         c = KCursor::sizeFDiagCursor();
952 #endif
953         break;
954     case CURSOR_TEXT:
955         c = KCursor::ibeamCursor();
956         break;
957     case CURSOR_WAIT:
958         c = KCursor::waitCursor();
959         break;
960     case CURSOR_HELP:
961         c = KCursor::whatsThisCursor();
962         break;
963     case CURSOR_DEFAULT:
964         break;
965     }
966
967     QWidget *vp = viewport();
968     if ( vp->cursor().handle() != c.handle() ) {
969         if( c.handle() == KCursor::arrowCursor().handle())
970             vp->unsetCursor();
971         else
972             vp->setCursor( c );
973     }
974     d->prevMouseX = xm;
975     d->prevMouseY = ym;
976
977     if (!swallowEvent) {
978         khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
979         QApplication::sendEvent( m_part, &event );
980     }
981 }
982
983 void KHTMLView::resetCursor()
984 {
985     viewport()->unsetCursor();
986 }
987
988 void KHTMLView::invalidateClick()
989 {
990     d->clickCount = 0;
991 }
992
993 void KHTMLView::viewportMouseReleaseEvent( QMouseEvent * _mouse )
994 {
995     if ( !m_part->xmlDocImpl() ) return;
996
997     int xm, ym;
998     viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
999
1000     d->mousePressed = false;
1001
1002     //kdDebug( 6000 ) << "\nmouseReleaseEvent: x=" << xm << ", y=" << ym << endl;
1003
1004     DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseRelease );
1005     m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
1006 #if APPLE_CHANGES
1007     if (KWQ(m_part)->passSubframeEventToSubframe(mev))
1008         return;
1009 #endif
1010
1011     bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,mev.innerNode.handle(),true,
1012                                            d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease);
1013
1014     if (d->clickCount > 0
1015 #if !APPLE_CHANGES
1016             && QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance()
1017 #endif
1018         )
1019         dispatchMouseEvent(EventImpl::CLICK_EVENT,mev.innerNode.handle(),true,
1020                            d->clickCount,_mouse,true,DOM::NodeImpl::MouseRelease);
1021
1022     if (!swallowEvent) {
1023         khtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
1024         QApplication::sendEvent( m_part, &event );
1025     }
1026 }
1027
1028 void KHTMLView::keyPressEvent( QKeyEvent *_ke )
1029 {
1030     if (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()) {
1031         if (m_part->xmlDocImpl()->focusNode()->dispatchKeyEvent(_ke))
1032         {
1033             _ke->accept();
1034             return;
1035         }
1036     }
1037
1038 #if !APPLE_CHANGES
1039     int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
1040     if (_ke->state()&ShiftButton)
1041       switch(_ke->key())
1042         {
1043         case Key_Space:
1044             if ( d->vmode == QScrollView::AlwaysOff )
1045                 _ke->accept();
1046             else
1047                 scrollBy( 0, -clipper()->height() - offs );
1048             break;
1049         }
1050     else
1051         switch ( _ke->key() )
1052         {
1053         case Key_Down:
1054         case Key_J:
1055             if ( d->vmode == QScrollView::AlwaysOff )
1056                 _ke->accept();
1057             else
1058                 scrollBy( 0, 10 );
1059             break;
1060
1061         case Key_Space:
1062         case Key_Next:
1063             if ( d->vmode == QScrollView::AlwaysOff )
1064                 _ke->accept();
1065             else
1066                 scrollBy( 0, clipper()->height() - offs );
1067             break;
1068
1069         case Key_Up:
1070         case Key_K:
1071             if ( d->vmode == QScrollView::AlwaysOff )
1072                 _ke->accept();
1073             else
1074                 scrollBy( 0, -10 );
1075             break;
1076
1077         case Key_Prior:
1078             if ( d->vmode == QScrollView::AlwaysOff )
1079                 _ke->accept();
1080             else
1081                 scrollBy( 0, -clipper()->height() + offs );
1082             break;
1083         case Key_Right:
1084         case Key_L:
1085             if ( d->hmode == QScrollView::AlwaysOff )
1086                 _ke->accept();
1087             else
1088                 scrollBy( 10, 0 );
1089             break;
1090         case Key_Left:
1091         case Key_H:
1092             if ( d->hmode == QScrollView::AlwaysOff )
1093                 _ke->accept();
1094             else
1095                 scrollBy( -10, 0 );
1096             break;
1097         case Key_Enter:
1098         case Key_Return:
1099             // ### FIXME:
1100             // or even better to HTMLAnchorElementImpl::event()
1101             if (m_part->xmlDocImpl()) {
1102                 NodeImpl *n = m_part->xmlDocImpl()->focusNode();
1103                 if (n)
1104                     n->setActive();
1105                 d->originalNode = n;
1106             }
1107             break;
1108         case Key_Home:
1109             if ( d->vmode == QScrollView::AlwaysOff )
1110                 _ke->accept();
1111             else
1112                 setContentsPos( 0, 0 );
1113             break;
1114         case Key_End:
1115             if ( d->vmode == QScrollView::AlwaysOff )
1116                 _ke->accept();
1117             else
1118                 setContentsPos( 0, contentsHeight() - visibleHeight() );
1119             break;
1120         default:
1121             _ke->ignore();
1122             return;
1123         }
1124     _ke->accept();
1125 #endif
1126 }
1127
1128 void KHTMLView::keyReleaseEvent(QKeyEvent *_ke)
1129 {
1130     if(m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()) {
1131         // Qt is damn buggy. we receive release events from our child
1132         // widgets. therefore, do not support keyrelease event on generic
1133         // nodes for now until we found  a workaround for the Qt bugs. (Dirk)
1134 //         if (m_part->xmlDocImpl()->focusNode()->dispatchKeyEvent(_ke)) {
1135 //             _ke->accept();
1136 //             return;
1137 //         }
1138 //        QScrollView::keyReleaseEvent(_ke);
1139         Q_UNUSED(_ke);
1140     }
1141 }
1142
1143 void KHTMLView::contentsContextMenuEvent ( QContextMenuEvent *_ce )
1144 {
1145 // ### what kind of c*** is that ?
1146 #if 0
1147     if (!m_part->xmlDocImpl()) return;
1148     int xm = _ce->x();
1149     int ym = _ce->y();
1150
1151     DOM::NodeImpl::MouseEvent mev( _ce->state(), DOM::NodeImpl::MouseMove ); // ### not a mouse event!
1152     m_part->xmlDocImpl()->prepareMouseEvent( xm, ym, &mev );
1153
1154     NodeImpl *targetNode = mev.innerNode.handle();
1155     if (targetNode && targetNode->renderer() && targetNode->renderer()->isWidget()) {
1156         int absx = 0;
1157         int absy = 0;
1158         targetNode->renderer()->absolutePosition(absx,absy);
1159         QPoint pos(xm-absx,ym-absy);
1160
1161         QWidget *w = static_cast<RenderWidget*>(targetNode->renderer())->widget();
1162         QContextMenuEvent cme(_ce->reason(),pos,_ce->globalPos(),_ce->state());
1163         setIgnoreEvents(true);
1164         QApplication::sendEvent(w,&cme);
1165         setIgnoreEvents(false);
1166     }
1167 #endif
1168 }
1169
1170 bool KHTMLView::dispatchDragEvent(int eventId, DOM::NodeImpl *dragTarget, const QPoint &loc, DOM::ClipboardImpl *clipboard)
1171 {
1172     int clientX, clientY;
1173     viewportToContents(loc.x(), loc.y(), clientX, clientY);
1174 #if APPLE_CHANGES
1175     QPoint screenLoc = viewportToGlobal(loc);
1176     int screenX = screenLoc.x();
1177     int screenY = screenLoc.y();
1178 #else
1179 #warning Need implementation of converting event location to screen location
1180     int screenX = loc.x();
1181     int screenY = loc.y();
1182 #endif
1183     bool ctrlKey = 0;   // FIXME - set up modifiers, grab from AK or CG
1184     bool altKey = 0;
1185     bool shiftKey = 0;
1186     bool metaKey = 0;
1187     
1188     MouseEventImpl *me = new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
1189                                             true, true, m_part->xmlDocImpl()->defaultView(),
1190                                             0, screenX, screenY, clientX, clientY,
1191                                             ctrlKey, altKey, shiftKey, metaKey,
1192                                             0, 0, clipboard);
1193     me->ref();
1194     int exceptioncode = 0;
1195     dragTarget->dispatchEvent(me, exceptioncode, true);
1196     bool accept = me->defaultPrevented();
1197     me->deref();
1198     return accept;
1199 }
1200
1201 bool KHTMLView::updateDragAndDrop(const QPoint &loc, DOM::ClipboardImpl *clipboard)
1202 {
1203     bool accept = false;
1204     int xm, ym;
1205     viewportToContents(loc.x(), loc.y(), xm, ym);
1206     DOM::NodeImpl::MouseEvent mev(0, DOM::NodeImpl::MouseMove);
1207     m_part->xmlDocImpl()->prepareMouseEvent(true, xm, ym, &mev);
1208     DOM::Node newTarget = mev.innerNode;
1209
1210     // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
1211     if (newTarget.nodeType() == Node::TEXT_NODE) {
1212         newTarget = newTarget.parentNode();
1213     }
1214
1215     if (d->dragTarget != newTarget) {
1216         // note this ordering is explicitly chosen to match WinIE
1217         if (!newTarget.isNull()) {
1218             accept = dispatchDragEvent(EventImpl::DRAGENTER_EVENT, newTarget.handle(), loc, clipboard);
1219         }
1220         if (!d->dragTarget.isNull()) {
1221             dispatchDragEvent(EventImpl::DRAGLEAVE_EVENT, d->dragTarget.handle(), loc, clipboard);
1222         }
1223     } else if (!newTarget.isNull()) {
1224         accept = dispatchDragEvent(EventImpl::DRAGOVER_EVENT, newTarget.handle(), loc, clipboard);
1225     }
1226     d->dragTarget = newTarget;
1227
1228     return accept;
1229 }
1230
1231 void KHTMLView::cancelDragAndDrop(const QPoint &loc, DOM::ClipboardImpl *clipboard)
1232 {
1233     if (!d->dragTarget.isNull()) {
1234         dispatchDragEvent(EventImpl::DRAGLEAVE_EVENT, d->dragTarget.handle(), loc, clipboard);
1235     }
1236     d->dragTarget = 0;
1237 }
1238
1239 bool KHTMLView::performDragAndDrop(const QPoint &loc, DOM::ClipboardImpl *clipboard)
1240 {
1241     bool accept = false;
1242     if (!d->dragTarget.isNull()) {
1243         accept = dispatchDragEvent(EventImpl::DROP_EVENT, d->dragTarget.handle(), loc, clipboard);
1244     }
1245     d->dragTarget = 0;
1246     return accept;
1247 }
1248
1249 #if !APPLE_CHANGES
1250
1251 bool KHTMLView::focusNextPrevChild( bool next )
1252 {
1253     // Now try to find the next child
1254     if (m_part->xmlDocImpl()) {
1255         focusNextPrevNode(next);
1256         if (m_part->xmlDocImpl()->focusNode() != 0)
1257             return true; // focus node found
1258     }
1259
1260     // If we get here, there is no next/previous child to go to, so pass up to the next/previous child in our parent
1261     if (m_part->parentPart() && m_part->parentPart()->view()) {
1262         return m_part->parentPart()->view()->focusNextPrevChild(next);
1263     }
1264
1265     return QWidget::focusNextPrevChild(next);
1266 }
1267
1268 void KHTMLView::doAutoScroll()
1269 {
1270     QPoint pos = QCursor::pos();
1271     pos = viewport()->mapFromGlobal( pos );
1272
1273     int xm, ym;
1274     viewportToContents(pos.x(), pos.y(), xm, ym);
1275
1276     pos = QPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y());
1277     if ( (pos.y() < 0) || (pos.y() > visibleHeight()) ||
1278          (pos.x() < 0) || (pos.x() > visibleWidth()) )
1279     {
1280         ensureVisible( xm, ym, 0, 5 );
1281     }
1282 }
1283
1284 #endif
1285
1286 DOM::NodeImpl *KHTMLView::nodeUnderMouse() const
1287 {
1288     return d->underMouse;
1289 }
1290
1291 bool KHTMLView::scrollTo(const QRect &bounds)
1292 {
1293     d->scrollingSelf = true; // so scroll events get ignored
1294
1295     int x, y, xe, ye;
1296     x = bounds.left();
1297     y = bounds.top();
1298     xe = bounds.right();
1299     ye = bounds.bottom();
1300
1301     //kdDebug(6000)<<"scrolling coords: x="<<x<<" y="<<y<<" width="<<xe-x<<" height="<<ye-y<<endl;
1302
1303     int deltax;
1304     int deltay;
1305
1306     int curHeight = visibleHeight();
1307     int curWidth = visibleWidth();
1308
1309     if (ye-y>curHeight-d->borderY)
1310         ye  = y + curHeight - d->borderY;
1311
1312     if (xe-x>curWidth-d->borderX)
1313         xe = x + curWidth - d->borderX;
1314
1315     // is xpos of target left of the view's border?
1316     if (x < contentsX() + d->borderX )
1317             deltax = x - contentsX() - d->borderX;
1318     // is xpos of target right of the view's right border?
1319     else if (xe + d->borderX > contentsX() + curWidth)
1320             deltax = xe + d->borderX - ( contentsX() + curWidth );
1321     else
1322         deltax = 0;
1323
1324     // is ypos of target above upper border?
1325     if (y < contentsY() + d->borderY)
1326             deltay = y - contentsY() - d->borderY;
1327     // is ypos of target below lower border?
1328     else if (ye + d->borderY > contentsY() + curHeight)
1329             deltay = ye + d->borderY - ( contentsY() + curHeight );
1330     else
1331         deltay = 0;
1332
1333     int maxx = curWidth-d->borderX;
1334     int maxy = curHeight-d->borderY;
1335
1336     int scrollX,scrollY;
1337
1338     scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax>-maxx ? deltax : -maxx);
1339     scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay>-maxy ? deltay : -maxy);
1340
1341     if (contentsX() + scrollX < 0)
1342         scrollX = -contentsX();
1343     else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
1344         scrollX = contentsWidth() - visibleWidth() - contentsX();
1345
1346     if (contentsY() + scrollY < 0)
1347         scrollY = -contentsY();
1348     else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
1349         scrollY = contentsHeight() - visibleHeight() - contentsY();
1350
1351     scrollBy(scrollX, scrollY);
1352
1353
1354
1355     // generate abs(scroll.)
1356     if (scrollX<0)
1357         scrollX=-scrollX;
1358     if (scrollY<0)
1359         scrollY=-scrollY;
1360
1361     d->scrollingSelf = false;
1362
1363     if ( (scrollX!=maxx) && (scrollY!=maxy) )
1364         return true;
1365     else return false;
1366
1367 }
1368
1369 void KHTMLView::focusNextPrevNode(bool next)
1370 {
1371     // Sets the focus node of the document to be the node after (or if next is false, before) the current focus node.
1372     // Only nodes that are selectable (i.e. for which isSelectable() returns true) are taken into account, and the order
1373     // used is that specified in the HTML spec (see DocumentImpl::nextFocusNode() and DocumentImpl::previousFocusNode()
1374     // for details).
1375
1376     DocumentImpl *doc = m_part->xmlDocImpl();
1377     NodeImpl *oldFocusNode = doc->focusNode();
1378     NodeImpl *newFocusNode;
1379
1380     // Find the next/previous node from the current one
1381     if (next)
1382         newFocusNode = doc->nextFocusNode(oldFocusNode);
1383     else
1384         newFocusNode = doc->previousFocusNode(oldFocusNode);
1385
1386     // If there was previously no focus node and the user has scrolled the document, then instead of picking the first
1387     // focusable node in the document, use the first one that lies within the visible area (if possible).
1388     if (!oldFocusNode && newFocusNode && d->scrollBarMoved) {
1389
1390       kdDebug(6000) << " searching for visible link" << endl;
1391
1392         bool visible = false;
1393         NodeImpl *toFocus = newFocusNode;
1394         while (!visible && toFocus) {
1395             QRect focusNodeRect = toFocus->getRect();
1396             if ((focusNodeRect.left() > contentsX()) && (focusNodeRect.right() < contentsX() + visibleWidth()) &&
1397                 (focusNodeRect.top() > contentsY()) && (focusNodeRect.bottom() < contentsY() + visibleHeight())) {
1398                 // toFocus is visible in the contents area
1399                 visible = true;
1400             }
1401             else {
1402                 // toFocus is _not_ visible in the contents area, pick the next node
1403                 if (next)
1404                     toFocus = doc->nextFocusNode(toFocus);
1405                 else
1406                     toFocus = doc->previousFocusNode(toFocus);
1407             }
1408         }
1409
1410         if (toFocus)
1411             newFocusNode = toFocus;
1412     }
1413
1414     d->scrollBarMoved = false;
1415
1416     if (!newFocusNode)
1417       {
1418         // No new focus node, scroll to bottom or top depending on next
1419         if (next)
1420             scrollTo(QRect(contentsX()+visibleWidth()/2,contentsHeight(),0,0));
1421         else
1422             scrollTo(QRect(contentsX()+visibleWidth()/2,0,0,0));
1423     }
1424     else {
1425         // EDIT FIXME: if it's an editable element, activate the caret
1426         // otherwise, hide it
1427         if (newFocusNode->isContentEditable()) {
1428             // make caret visible
1429         } 
1430         else {
1431             // hide caret
1432         }
1433
1434         // Scroll the view as necessary to ensure that the new focus node is visible
1435         if (oldFocusNode) {
1436             if (!scrollTo(newFocusNode->getRect()))
1437                 return;
1438         }
1439         else {
1440             ensureVisible(contentsX(), next ? 0: contentsHeight());
1441         }
1442     }
1443     // Set focus node on the document
1444     m_part->xmlDocImpl()->setFocusNode(newFocusNode);
1445     emit m_part->nodeActivated(Node(newFocusNode));
1446
1447 #if 0
1448     if (newFocusNode) {
1449
1450         // this does not belong here. it should run a query on the tree (Dirk)
1451         // I'll fix this very particular part of the code soon when I cleaned
1452         // up the positioning code
1453         // If the newly focussed node is a link, notify the part
1454
1455         HTMLAnchorElementImpl *anchor = 0;
1456         if ((newFocusNode->id() == ID_A || newFocusNode->id() == ID_AREA))
1457             anchor = static_cast<HTMLAnchorElementImpl *>(newFocusNode);
1458
1459         if (anchor && !anchor->areaHref().isNull())
1460             m_part->overURL(anchor->areaHref().string(), 0);
1461         else
1462             m_part->overURL(QString(), 0);
1463     }
1464 #endif
1465 }
1466
1467 void KHTMLView::setMediaType( const QString &medium )
1468 {
1469     m_medium = medium;
1470 }
1471
1472 QString KHTMLView::mediaType() const
1473 {
1474 #if APPLE_CHANGES
1475     // See if we have an override type.
1476     QString overrideType = KWQ(m_part)->overrideMediaType();
1477     if (!overrideType.isNull())
1478         return overrideType;
1479 #endif
1480     return m_medium;
1481 }
1482
1483 #if !APPLE_CHANGES
1484
1485 void KHTMLView::print()
1486 {
1487     if(!m_part->xmlDocImpl()) return;
1488     khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
1489     if(!root) return;
1490
1491     // this only works on Unix - we assume 72dpi
1492     KPrinter *printer = new KPrinter(QPrinter::PrinterResolution);
1493     printer->addDialogPage(new KHTMLPrintSettings());
1494     if(printer->setup(this)) {
1495         viewport()->setCursor( waitCursor ); // only viewport(), no QApplication::, otherwise we get the busy cursor in kdeprint's dialogs
1496         // set up KPrinter
1497         printer->setFullPage(false);
1498         printer->setCreator("KDE 3.0 HTML Library");
1499         QString docname = m_part->xmlDocImpl()->URL();
1500         if ( !docname.isEmpty() )
1501             printer->setDocName(docname);
1502
1503         QPainter *p = new QPainter;
1504         p->begin( printer );
1505         khtml::setPrintPainter( p );
1506
1507         m_part->xmlDocImpl()->setPaintDevice( printer );
1508         QString oldMediaType = mediaType();
1509         setMediaType( "print" );
1510         // We ignore margin settings for html and body when printing
1511         // and use the default margins from the print-system
1512         // (In Qt 3.0.x the default margins are hardcoded in Qt)
1513         m_part->xmlDocImpl()->setPrintStyleSheet( printer->option("kde-khtml-printfriendly") == "true" ?
1514                                                   "* { background-image: none !important;"
1515                                                   "    background-color: white !important;"
1516                                                   "    color: black !important; }"
1517                                                   "body { margin: 0px !important; }"
1518                                                   "html { margin: 0px !important; }" :
1519                                                   "body { margin: 0px !important; }"
1520                                                   "html { margin: 0px !important; }"
1521                                                   );
1522
1523
1524         QPaintDeviceMetrics metrics( printer );
1525
1526         // this is a simple approximation... we layout the document
1527         // according to the width of the page, then just cut
1528         // pages without caring about the content. We should do better
1529         // in the future, but for the moment this is better than no
1530         // printing support
1531         kdDebug(6000) << "printing: physical page width = " << metrics.width()
1532                       << " height = " << metrics.height() << endl;
1533         root->setPrintingMode(true);
1534         root->setWidth(metrics.width());
1535
1536         m_part->xmlDocImpl()->styleSelector()->computeFontSizes(&metrics);
1537         m_part->xmlDocImpl()->updateStyleSelector();
1538         root->setPrintImages( printer->option("kde-khtml-printimages") == "true");
1539         root->setNeedsLayoutAndMinMaxRecalc();
1540         root->layout();
1541
1542         // ok. now print the pages.
1543         kdDebug(6000) << "printing: html page width = " << root->docWidth()
1544                       << " height = " << root->docHeight() << endl;
1545         kdDebug(6000) << "printing: margins left = " << printer->margins().width()
1546                       << " top = " << printer->margins().height() << endl;
1547         kdDebug(6000) << "printing: paper width = " << metrics.width()
1548                       << " height = " << metrics.height() << endl;
1549         // if the width is too large to fit on the paper we just scale
1550         // the whole thing.
1551         int pageHeight = metrics.height();
1552         int pageWidth = metrics.width();
1553         p->setClipRect(0,0, pageWidth, pageHeight);
1554         if(root->docWidth() > metrics.width()) {
1555             double scale = ((double) metrics.width())/((double) root->docWidth());
1556 #ifndef QT_NO_TRANSFORMATIONS
1557             p->scale(scale, scale);
1558 #endif
1559             pageHeight = (int) (pageHeight/scale);
1560             pageWidth = (int) (pageWidth/scale);
1561         }
1562         kdDebug(6000) << "printing: scaled html width = " << pageWidth
1563                       << " height = " << pageHeight << endl;
1564         int top = 0;
1565         while(top < root->docHeight()) {
1566             if(top > 0) printer->newPage();
1567             root->setTruncatedAt(top+pageHeight);
1568
1569             root->print(p, 0, top, pageWidth, pageHeight, 0, 0);
1570             if (top + pageHeight >= root->docHeight())
1571                 break; // Stop if we have printed everything
1572
1573             p->translate(0, top - root->truncatedAt());
1574             top = root->truncatedAt();
1575         }
1576
1577         p->end();
1578         delete p;
1579
1580         // and now reset the layout to the usual one...
1581         root->setPrintingMode(false);
1582         khtml::setPrintPainter( 0 );
1583         setMediaType( oldMediaType );
1584         m_part->xmlDocImpl()->setPaintDevice( this );
1585         m_part->xmlDocImpl()->styleSelector()->computeFontSizes(m_part->xmlDocImpl()->paintDeviceMetrics());
1586         m_part->xmlDocImpl()->updateStyleSelector();
1587         viewport()->unsetCursor();
1588     }
1589     delete printer;
1590 }
1591
1592 void KHTMLView::slotPaletteChanged()
1593 {
1594     if(!m_part->xmlDocImpl()) return;
1595     DOM::DocumentImpl *document = m_part->xmlDocImpl();
1596     if (!document->isHTMLDocument()) return;
1597     khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(document->renderer());
1598     if(!root) return;
1599     root->style()->resetPalette();
1600     NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
1601     if(!body) return;
1602     body->setChanged(true);
1603     body->recalcStyle( NodeImpl::Force );
1604 }
1605
1606 void KHTMLView::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
1607 {
1608     if(!m_part->xmlDocImpl()) return;
1609     khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
1610     if(!root) return;
1611
1612     m_part->xmlDocImpl()->setPaintDevice(p->device());
1613     root->setPrintingMode(true);
1614     root->setWidth(rc.width());
1615
1616     p->save();
1617     p->setClipRect(rc);
1618     p->translate(rc.left(), rc.top());
1619     double scale = ((double) rc.width()/(double) root->docWidth());
1620     int height = (int) ((double) rc.height() / scale);
1621 #ifndef QT_NO_TRANSFORMATIONS
1622     p->scale(scale, scale);
1623 #endif
1624
1625     root->print(p, 0, yOff, root->docWidth(), height, 0, 0);
1626     if (more)
1627         *more = yOff + height < root->docHeight();
1628     p->restore();
1629
1630     root->setPrintingMode(false);
1631     m_part->xmlDocImpl()->setPaintDevice( this );
1632 }
1633
1634 #endif // !APPLE_CHANGES
1635
1636 void KHTMLView::useSlowRepaints()
1637 {
1638     kdDebug(0) << "slow repaints requested" << endl;
1639     d->useSlowRepaints = true;
1640     setStaticBackground(true);
1641 }
1642
1643 void KHTMLView::setScrollBarsMode ( ScrollBarMode mode )
1644 {
1645 #ifndef KHTML_NO_SCROLLBARS
1646     d->vmode = mode;
1647     d->hmode = mode;
1648     
1649 #if APPLE_CHANGES
1650     QScrollView::setScrollBarsMode(mode);
1651 #else
1652     QScrollView::setVScrollBarMode(mode);
1653     QScrollView::setHScrollBarMode(mode);
1654 #endif
1655 #else
1656     Q_UNUSED( mode );
1657 #endif
1658 }
1659
1660 void KHTMLView::setVScrollBarMode ( ScrollBarMode mode )
1661 {
1662 #ifndef KHTML_NO_SCROLLBARS
1663     d->vmode = mode;
1664     QScrollView::setVScrollBarMode(mode);
1665 #else
1666     Q_UNUSED( mode );
1667 #endif
1668 }
1669
1670 void KHTMLView::setHScrollBarMode ( ScrollBarMode mode )
1671 {
1672 #ifndef KHTML_NO_SCROLLBARS
1673     d->hmode = mode;
1674     QScrollView::setHScrollBarMode(mode);
1675 #else
1676     Q_UNUSED( mode );
1677 #endif
1678 }
1679
1680 void KHTMLView::restoreScrollBar ( )
1681 {
1682 #if APPLE_CHANGES
1683     suppressScrollBars(false);
1684 #else
1685     int ow = visibleWidth();
1686     QScrollView::setVScrollBarMode(d->vmode);
1687     if (visibleWidth() != ow)
1688         layout();
1689     d->prevScrollbarVisible = verticalScrollBar()->isVisible();
1690 #endif
1691 }
1692
1693 #if !APPLE_CHANGES
1694
1695 QStringList KHTMLView::formCompletionItems(const QString &name) const
1696 {
1697     if (!m_part->settings()->isFormCompletionEnabled())
1698         return QStringList();
1699     if (!d->formCompletions)
1700         d->formCompletions = new KSimpleConfig(locateLocal("data", "khtml/formcompletions"));
1701     return d->formCompletions->readListEntry(name);
1702 }
1703
1704 void KHTMLView::addFormCompletionItem(const QString &name, const QString &value)
1705 {
1706     if (!m_part->settings()->isFormCompletionEnabled())
1707         return;
1708     // don't store values that are all numbers or just numbers with
1709     // dashes or spaces as those are likely credit card numbers or
1710     // something similar
1711     bool cc_number(true);
1712     for (unsigned int i = 0; i < value.length(); ++i)
1713     {
1714       QChar c(value[i]);
1715       if (!c.isNumber() && c != '-' && !c.isSpace())
1716       {
1717         cc_number = false;
1718         break;
1719       }
1720     }
1721     if (cc_number)
1722       return;
1723     QStringList items = formCompletionItems(name);
1724     if (!items.contains(value))
1725         items.prepend(value);
1726     while ((int)items.count() > m_part->settings()->maxFormCompletionItems())
1727         items.remove(items.fromLast());
1728     d->formCompletions->writeEntry(name, items);
1729 }
1730
1731 #endif
1732
1733 bool KHTMLView::dispatchMouseEvent(int eventId, DOM::NodeImpl *targetNode, bool cancelable,
1734                                    int detail,QMouseEvent *_mouse, bool setUnder,
1735                                    int mouseEventType)
1736 {
1737     if (d->underMouse)
1738         d->underMouse->deref();
1739     d->underMouse = targetNode;
1740     if (d->underMouse)
1741         d->underMouse->ref();
1742
1743     int exceptioncode = 0;
1744     int clientX, clientY;
1745     viewportToContents(_mouse->x(), _mouse->y(), clientX, clientY);
1746 #if APPLE_CHANGES
1747     QPoint screenLoc = viewportToGlobal(_mouse->pos());
1748     int screenX = screenLoc.x();
1749     int screenY = screenLoc.y();
1750 #else
1751     int screenX = _mouse->globalX();
1752     int screenY = _mouse->globalY();
1753 #endif
1754     int button = -1;
1755     switch (_mouse->button()) {
1756         case LeftButton:
1757             button = 0;
1758             break;
1759         case MidButton:
1760             button = 1;
1761             break;
1762         case RightButton:
1763             button = 2;
1764             break;
1765         default:
1766             break;
1767     }
1768     bool ctrlKey = (_mouse->state() & ControlButton);
1769     bool altKey = (_mouse->state() & AltButton);
1770     bool shiftKey = (_mouse->state() & ShiftButton);
1771     bool metaKey = (_mouse->state() & MetaButton);
1772
1773     // mouseout/mouseover
1774     if (setUnder && (d->prevMouseX != clientX || d->prevMouseY != clientY)) {
1775
1776         // ### this code sucks. we should save the oldUnder instead of calculating
1777         // it again. calculating is expensive! (Dirk)
1778         NodeImpl *oldUnder = 0;
1779         if (d->prevMouseX >= 0 && d->prevMouseY >= 0) {
1780             NodeImpl::MouseEvent mev( _mouse->stateAfter(), static_cast<NodeImpl::MouseEventType>(mouseEventType));
1781             m_part->xmlDocImpl()->prepareMouseEvent( true, d->prevMouseX, d->prevMouseY, &mev );
1782             oldUnder = mev.innerNode.handle();
1783         }
1784         if (oldUnder != targetNode) {
1785             // send mouseout event to the old node
1786             if (oldUnder){
1787                 oldUnder->ref();
1788                 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOUT_EVENT,
1789                                                         true,true,m_part->xmlDocImpl()->defaultView(),
1790                                                         0,screenX,screenY,clientX,clientY,
1791                                                         ctrlKey,altKey,shiftKey,metaKey,
1792                                                         button,targetNode);
1793                 me->ref();
1794                 oldUnder->dispatchEvent(me,exceptioncode,true);
1795                 me->deref();
1796             }
1797
1798             // send mouseover event to the new node
1799             if (targetNode) {
1800                 MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOVER_EVENT,
1801                                                         true,true,m_part->xmlDocImpl()->defaultView(),
1802                                                         0,screenX,screenY,clientX,clientY,
1803                                                         ctrlKey,altKey,shiftKey,metaKey,
1804                                                         button,oldUnder);
1805
1806                 me->ref();
1807                 targetNode->dispatchEvent(me,exceptioncode,true);
1808                 me->deref();
1809             }
1810
1811             if (oldUnder)
1812                 oldUnder->deref();
1813         }
1814     }
1815
1816     bool swallowEvent = false;
1817
1818     if (targetNode) {
1819         // send the actual event
1820         MouseEventImpl *me = new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
1821                                                 true,cancelable,m_part->xmlDocImpl()->defaultView(),
1822                                                 detail,screenX,screenY,clientX,clientY,
1823                                                 ctrlKey,altKey,shiftKey,metaKey,
1824                                                 button,0);
1825         me->ref();
1826         targetNode->dispatchEvent(me,exceptioncode,true);
1827         bool defaultHandled = me->defaultHandled();
1828         if (me->defaultHandled() || me->defaultPrevented())
1829             swallowEvent = true;
1830         me->deref();
1831
1832         // Special case: If it's a click event, we also send the KHTML_CLICK or KHTML_DBLCLICK event. This is not part
1833         // of the DOM specs, but is used for compatibility with the traditional onclick="" and ondblclick="" attributes,
1834         // as there is no way to tell the difference between single & double clicks using DOM (only the click count is
1835         // stored, which is not necessarily the same)
1836         if (eventId == EventImpl::CLICK_EVENT) {
1837             me = new MouseEventImpl(d->isDoubleClick ? EventImpl::KHTML_DBLCLICK_EVENT : EventImpl::KHTML_CLICK_EVENT,
1838                                     true,cancelable,m_part->xmlDocImpl()->defaultView(),
1839                                     detail,screenX,screenY,clientX,clientY,
1840                                     ctrlKey,altKey,shiftKey,metaKey,
1841                                     button,0);
1842
1843             me->ref();
1844             if (defaultHandled)
1845                 me->setDefaultHandled();
1846             targetNode->dispatchEvent(me,exceptioncode,true);
1847             if (me->defaultHandled() || me->defaultPrevented())
1848                 swallowEvent = true;
1849             me->deref();
1850         }
1851         else if (eventId == EventImpl::MOUSEDOWN_EVENT) {
1852             // Focus should be shifted on mouse down, not on a click.  -dwh
1853             // Blur current focus node when a link/button is clicked; this
1854             // is expected by some sites that rely on onChange handlers running
1855             // from form fields before the button click is processed.
1856             DOM::NodeImpl* nodeImpl = targetNode;
1857             for ( ; nodeImpl && !nodeImpl->isFocusable(); nodeImpl = nodeImpl->parentNode());
1858             // If focus shift is blocked, we eat the event.  Note we should never clear swallowEvent
1859             // if the page already set it (e.g., by canceling default behavior).
1860             if (nodeImpl && nodeImpl->isMouseFocusable())
1861                 swallowEvent |= !m_part->xmlDocImpl()->setFocusNode(nodeImpl);
1862             else if (!nodeImpl || !nodeImpl->focused())
1863                 swallowEvent |= !m_part->xmlDocImpl()->setFocusNode(0);
1864         }
1865     }
1866
1867     return swallowEvent;
1868 }
1869
1870 void KHTMLView::setIgnoreWheelEvents( bool e )
1871 {
1872     d->ignoreWheelEvents = e;
1873 }
1874
1875 #ifndef QT_NO_WHEELEVENT
1876
1877 void KHTMLView::viewportWheelEvent(QWheelEvent* e)
1878 {
1879 #if !APPLE_CHANGES
1880     if ( d->ignoreWheelEvents && !verticalScrollBar()->isVisible() && m_part->parentPart() ) {
1881         if ( m_part->parentPart()->view() )
1882             m_part->parentPart()->view()->wheelEvent( e );
1883         e->ignore();
1884     }
1885     else if ( d->vmode == QScrollView::AlwaysOff ) {
1886         e->accept();
1887     }
1888     else {
1889         d->scrollBarMoved = true;
1890         QScrollView::viewportWheelEvent( e );
1891     }
1892 #endif
1893 }
1894 #endif
1895
1896 #if !APPLE_CHANGES
1897 void KHTMLView::dragEnterEvent( QDragEnterEvent* ev )
1898 {
1899     // Handle drops onto frames (#16820)
1900     // Drops on the main html part is handled by Konqueror (and shouldn't do anything
1901     // in e.g. kmail, so not handled here).
1902     if ( m_part->parentPart() )
1903     {
1904         // Duplicated from KonqView::eventFilter
1905         if ( QUriDrag::canDecode( ev ) )
1906         {
1907             KURL::List lstDragURLs;
1908             bool ok = KURLDrag::decode( ev, lstDragURLs );
1909             QObjectList *children = this->queryList( "QWidget" );
1910
1911             if ( ok &&
1912                  !lstDragURLs.first().url().contains( "javascript:", false ) && // ### this looks like a hack to me
1913                  ev->source() != this &&
1914                  children &&
1915                  children->findRef( ev->source() ) == -1 )
1916                 ev->acceptAction();
1917
1918             delete children;
1919         }
1920     }
1921     QScrollView::dragEnterEvent( ev );
1922 }
1923
1924 void KHTMLView::dropEvent( QDropEvent *ev )
1925 {
1926     // Handle drops onto frames (#16820)
1927     // Drops on the main html part is handled by Konqueror (and shouldn't do anything
1928     // in e.g. kmail, so not handled here).
1929     if ( m_part->parentPart() )
1930     {
1931         KURL::List lstDragURLs;
1932         bool ok = KURLDrag::decode( ev, lstDragURLs );
1933
1934         KHTMLPart* part = m_part->parentPart();
1935         while ( part && part->parentPart() )
1936             part = part->parentPart();
1937         KParts::BrowserExtension *ext = part->browserExtension();
1938         if ( ok && ext && lstDragURLs.first().isValid() )
1939             emit ext->openURLRequest( lstDragURLs.first() );
1940     }
1941     QScrollView::dropEvent( ev );
1942 }
1943 #endif // !APPLE_CHANGES
1944
1945 void KHTMLView::focusInEvent( QFocusEvent *e )
1946 {
1947     m_part->setCaretVisible();
1948     QScrollView::focusInEvent( e );
1949 }
1950
1951 void KHTMLView::focusOutEvent( QFocusEvent *e )
1952 {
1953     m_part->stopAutoScroll();
1954     m_part->setCaretVisible(false);
1955     QScrollView::focusOutEvent( e );
1956 }
1957
1958 void KHTMLView::slotScrollBarMoved()
1959 {
1960     if (!d->scrollingSelf)
1961         d->scrollBarMoved = true;
1962 }
1963
1964 void KHTMLView::repaintRectangle(const QRect& r, bool immediate)
1965 {
1966     updateContents(r, immediate);
1967 }
1968
1969 void KHTMLView::timerEvent ( QTimerEvent *e )
1970 {
1971     if (e->timerId()==d->layoutTimerId)
1972         layout();
1973 }
1974
1975 void KHTMLView::scheduleRelayout()
1976 {
1977     if (!d->layoutSchedulingEnabled)
1978         return;
1979
1980     if (d->layoutTimerId || (m_part->xmlDocImpl() && !m_part->xmlDocImpl()->shouldScheduleLayout()))
1981         return;
1982
1983     d->allDataReceivedWhenTimerSet = m_part->xmlDocImpl() && !m_part->xmlDocImpl()->allDataReceived();
1984
1985 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
1986     if (!m_part->xmlDocImpl()->ownerElement())
1987         printf("Scheduling layout for %d\n", m_part->xmlDocImpl()->minimumLayoutDelay());
1988 #endif
1989
1990     d->layoutTimerId = startTimer(m_part->xmlDocImpl() ? m_part->xmlDocImpl()->minimumLayoutDelay() : 0);
1991 }
1992
1993 bool KHTMLView::haveDelayedLayoutScheduled()
1994 {
1995     return d->layoutTimerId && d->allDataReceivedWhenTimerSet;
1996 }
1997
1998 void KHTMLView::unscheduleRelayout()
1999 {
2000     if (!d->layoutTimerId)
2001         return;
2002
2003     killTimer(d->layoutTimerId);
2004     d->layoutTimerId = 0;
2005     d->allDataReceivedWhenTimerSet = false;
2006 }
2007
2008 bool KHTMLView::isTransparent() const
2009 {
2010     return d->isTransparent;
2011 }
2012
2013 void KHTMLView::setTransparent(bool isTransparent)
2014 {
2015     d->isTransparent = isTransparent;
2016 }
2017