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
#include "khtmlview.moc"
00027
00028
#include "khtmlview.h"
00029
00030
#include "khtml_part.h"
00031
#include "khtml_events.h"
00032
00033
#include "html/html_documentimpl.h"
00034
#include "html/html_inlineimpl.h"
00035
#include "html/html_formimpl.h"
00036
#include "rendering/render_arena.h"
00037
#include "rendering/render_canvas.h"
00038
#include "rendering/render_frames.h"
00039
#include "rendering/render_replaced.h"
00040
#include "rendering/render_layer.h"
00041
#include "rendering/render_line.h"
00042
#include "rendering/render_table.h"
00043
00044
#define protected public
00045
#include "rendering/render_text.h"
00046
#undef protected
00047
#include "xml/dom2_eventsimpl.h"
00048
#include "css/cssstyleselector.h"
00049
#include "misc/htmlhashes.h"
00050
#include "misc/helper.h"
00051
#include "khtml_settings.h"
00052
#include "khtml_printsettings.h"
00053
00054
#include "khtmlpart_p.h"
00055
00056
#ifndef KHTML_NO_CARET
00057
#include "khtml_caret_p.h"
00058
#include "xml/dom2_rangeimpl.h"
00059
#endif
00060
00061
#include <kcursor.h>
00062
#include <ksimpleconfig.h>
00063
#include <kstringhandler.h>
00064
#include <kstandarddirs.h>
00065
#include <kprinter.h>
00066
#include <klocale.h>
00067
00068
#include <qtooltip.h>
00069
#include <qpainter.h>
00070
#include <qpaintdevicemetrics.h>
00071
#include <qstylesheet.h>
00072
#include <kapplication.h>
00073
00074
#include <kimageio.h>
00075
#include <kdebug.h>
00076
#include <kurldrag.h>
00077
#include <qobjectlist.h>
00078
#include <qtimer.h>
00079
#include <kdialogbase.h>
00080
#include <qptrdict.h>
00081
00082
00083
00084
00085
00086
00087
00088
#define PAINT_BUFFER_HEIGHT 128
00089
00090
using namespace DOM;
00091
using namespace khtml;
00092
class KHTMLToolTip;
00093
00094
#ifndef QT_NO_TOOLTIP
00095
00096
class KHTMLToolTip :
public QToolTip
00097 {
00098
public:
00099 KHTMLToolTip(
KHTMLView *view, KHTMLViewPrivate* vp) :
QToolTip(view->viewport())
00100 {
00101 m_view = view;
00102 m_viewprivate = vp;
00103 };
00104
00105
protected:
00106
virtual void maybeTip(
const QPoint &);
00107
00108
private:
00109
KHTMLView *m_view;
00110 KHTMLViewPrivate* m_viewprivate;
00111 };
00112
00113
#endif
00114
00115
class KHTMLViewPrivate {
00116
friend class KHTMLToolTip;
00117
public:
00118 KHTMLViewPrivate()
00119 : underMouse( 0 )
00120 {
00121
#ifndef KHTML_NO_CARET
00122
m_caretViewContext = 0;
00123 m_editorContext = 0;
00124
#endif // KHTML_NO_CARET
00125
postponed_autorepeat = NULL;
00126 reset();
00127 tp=0;
00128 paintBuffer=0;
00129 vertPaintBuffer=0;
00130 formCompletions=0;
00131 prevScrollbarVisible =
true;
00132 tooltip = 0;
00133 possibleTripleClick =
false;
00134 }
00135 ~KHTMLViewPrivate()
00136 {
00137
delete formCompletions;
00138
delete tp; tp = 0;
00139
delete paintBuffer; paintBuffer =0;
00140
delete vertPaintBuffer;
00141
delete postponed_autorepeat;
00142
if (underMouse)
00143 underMouse->deref();
00144
delete tooltip;
00145
#ifndef KHTML_NO_CARET
00146
delete m_caretViewContext;
00147
delete m_editorContext;
00148
#endif // KHTML_NO_CARET
00149
}
00150
void reset()
00151 {
00152
if (underMouse)
00153 underMouse->deref();
00154 underMouse = 0;
00155 linkPressed =
false;
00156 useSlowRepaints =
false;
00157 originalNode = 0;
00158 borderTouched =
false;
00159
#ifndef KHTML_NO_SCROLLBARS
00160
vmode = QScrollView::Auto;
00161 hmode = QScrollView::Auto;
00162
#else
00163
vmode = QScrollView::AlwaysOff;
00164 hmode = QScrollView::AlwaysOff;
00165
#endif
00166
#ifdef DEBUG_PIXEL
00167
timer.start();
00168 pixelbooth = 0;
00169 repaintbooth = 0;
00170
#endif
00171
scrollBarMoved =
false;
00172 ignoreWheelEvents =
false;
00173 borderX = 30;
00174 borderY = 30;
00175 clickX = -1;
00176 clickY = -1;
00177 prevMouseX = -1;
00178 prevMouseY = -1;
00179 clickCount = 0;
00180 isDoubleClick =
false;
00181 scrollingSelf =
false;
00182
delete postponed_autorepeat;
00183 postponed_autorepeat = NULL;
00184 layoutTimerId = 0;
00185 repaintTimerId = 0;
00186 scrollTimerId = 0;
00187 scrollSuspended =
false;
00188 complete =
false;
00189 firstRelayout =
true;
00190 dirtyLayout =
false;
00191 layoutSchedulingEnabled =
true;
00192 updateRegion =
QRegion();
00193 m_dialogsAllowed =
true;
00194
#ifndef KHTML_NO_CARET
00195
if (m_caretViewContext) {
00196 m_caretViewContext->caretMoved =
false;
00197 m_caretViewContext->keyReleasePending =
false;
00198 }
00199
#endif // KHTML_NO_CARET
00200
}
00201
void newScrollTimer(
QWidget *view,
int tid)
00202 {
00203
00204 view->killTimer(scrollTimerId);
00205 scrollTimerId = tid;
00206 scrollSuspended =
false;
00207 }
00208
enum ScrollDirection { ScrollLeft, ScrollRight, ScrollUp, ScrollDown };
00209
00210
void adjustScroller(
QWidget *view, ScrollDirection direction, ScrollDirection oppositedir)
00211 {
00212
static const struct {
int msec, pixels; } timings [] = {
00213 {320,1}, {224,1}, {160,1}, {112,1}, {80,1}, {56,1}, {40,1},
00214 {28,1}, {20,1}, {20,2}, {20,3}, {20,4}, {20,6}, {20,8}, {0,0}
00215 };
00216
if (!scrollTimerId ||
00217 (scrollDirection != direction &&
00218 (scrollDirection != oppositedir || scrollSuspended))) {
00219 scrollTiming = 6;
00220 scrollBy = timings[scrollTiming].pixels;
00221 scrollDirection = direction;
00222 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00223 }
else if (scrollDirection == direction &&
00224 timings[scrollTiming+1].msec && !scrollSuspended) {
00225 scrollBy = timings[++scrollTiming].pixels;
00226 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00227 }
else if (scrollDirection == oppositedir) {
00228
if (scrollTiming) {
00229 scrollBy = timings[--scrollTiming].pixels;
00230 newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
00231 }
00232 }
00233 scrollSuspended =
false;
00234 }
00235
00236
#ifndef KHTML_NO_CARET
00237
00240
CaretViewContext *caretViewContext() {
00241
if (!m_caretViewContext) m_caretViewContext =
new CaretViewContext();
00242
return m_caretViewContext;
00243 }
00247
EditorContext *editorContext() {
00248
if (!m_editorContext) m_editorContext =
new EditorContext();
00249
return m_editorContext;
00250 }
00251
#endif // KHTML_NO_CARET
00252
00253
#ifdef DEBUG_PIXEL
00254
QTime timer;
00255
unsigned int pixelbooth;
00256
unsigned int repaintbooth;
00257
#endif
00258
00259
QPainter *tp;
00260
QPixmap *paintBuffer;
00261
QPixmap *vertPaintBuffer;
00262 NodeImpl *underMouse;
00263
00264
00265 NodeImpl *originalNode;
00266
00267
bool borderTouched:1;
00268
bool borderStart:1;
00269
bool scrollBarMoved:1;
00270
00271 QScrollView::ScrollBarMode vmode;
00272 QScrollView::ScrollBarMode hmode;
00273
bool prevScrollbarVisible;
00274
bool linkPressed;
00275
bool useSlowRepaints;
00276
bool ignoreWheelEvents;
00277
00278
int borderX, borderY;
00279
KSimpleConfig *formCompletions;
00280
00281
int clickX, clickY, clickCount;
00282
bool isDoubleClick;
00283
00284
int prevMouseX, prevMouseY;
00285
bool scrollingSelf;
00286
int layoutTimerId;
00287
QKeyEvent* postponed_autorepeat;
00288
00289
int repaintTimerId;
00290
int scrollTimerId;
00291
bool scrollSuspended;
00292
int scrollTiming;
00293
int scrollBy;
00294 ScrollDirection scrollDirection;
00295
bool complete;
00296
bool firstRelayout;
00297
bool layoutSchedulingEnabled;
00298
bool possibleTripleClick;
00299
bool dirtyLayout;
00300
bool m_dialogsAllowed;
00301
QRegion updateRegion;
00302 KHTMLToolTip *tooltip;
00303
QPtrDict<QWidget> visibleWidgets;
00304
#ifndef KHTML_NO_CARET
00305
CaretViewContext *m_caretViewContext;
00306
EditorContext *m_editorContext;
00307
#endif // KHTML_NO_CARET
00308
};
00309
00310
#ifndef QT_NO_TOOLTIP
00311
00312
void KHTMLToolTip::maybeTip(
const QPoint& )
00313 {
00314 DOM::NodeImpl *node = m_viewprivate->underMouse;
00315
QRect region;
00316
while ( node ) {
00317
if ( node->isElementNode() ) {
00318
QString s = static_cast<DOM::ElementImpl*>( node )->getAttribute( ATTR_TITLE ).string();
00319 region |=
QRect( m_view->contentsToViewport( node->getRect().topLeft() ), node->getRect().size() );
00320
if ( !s.
isEmpty() ) {
00321 tip( region, QStyleSheet::convertFromPlainText( s, QStyleSheetItem::WhiteSpaceNormal ) );
00322
break;
00323 }
00324 }
00325 node = node->parentNode();
00326 }
00327 }
00328
#endif
00329
00330 KHTMLView::KHTMLView(
KHTMLPart *part,
QWidget *parent,
const char *name)
00331 :
QScrollView( parent, name, WResizeNoErase | WRepaintNoErase )
00332 {
00333 m_medium =
"screen";
00334
00335 m_part = part;
00336 d =
new KHTMLViewPrivate;
00337
QScrollView::setVScrollBarMode(d->vmode);
00338
QScrollView::setHScrollBarMode(d->hmode);
00339 connect(kapp, SIGNAL(kdisplayPaletteChanged()),
this, SLOT(slotPaletteChanged()));
00340 connect(
this, SIGNAL(
contentsMoving(
int,
int)),
this, SLOT(slotScrollBarMoved()));
00341
00342
00343
enableClipper(
true);
00344
00345 static_cast<KHTMLView *>(static_cast<QWidget *>(
viewport()))->setWFlags(WPaintUnclipped);
00346
00347
setResizePolicy(Manual);
00348
viewport()->setMouseTracking(
true);
00349
viewport()->setBackgroundMode(NoBackground);
00350
00351
KImageIO::registerFormats();
00352
00353
#ifndef QT_NO_TOOLTIP
00354
d->tooltip =
new KHTMLToolTip(
this, d );
00355
#endif
00356
00357 init();
00358
00359
viewport()->show();
00360 }
00361
00362 KHTMLView::~KHTMLView()
00363 {
00364 closeChildDialogs();
00365
if (m_part)
00366 {
00367
00368
00369 DOM::DocumentImpl *doc = m_part->
xmlDocImpl();
00370
if (doc)
00371 doc->detach();
00372 }
00373
delete d; d = 0;
00374 }
00375
00376
void KHTMLView::init()
00377 {
00378
if(!d->paintBuffer) d->paintBuffer =
new QPixmap(PAINT_BUFFER_HEIGHT, PAINT_BUFFER_HEIGHT);
00379
if(!d->vertPaintBuffer)
00380 d->vertPaintBuffer =
new QPixmap(10, PAINT_BUFFER_HEIGHT);
00381
if(!d->tp) d->tp =
new QPainter();
00382
00383 setFocusPolicy(QWidget::StrongFocus);
00384
viewport()->setFocusProxy(
this);
00385
00386 _marginWidth = -1;
00387 _marginHeight = -1;
00388 _width = 0;
00389 _height = 0;
00390
00391 installEventFilter(
this);
00392
00393 setAcceptDrops(
true);
00394
QSize s =
viewportSize(4095, 4095);
00395
resizeContents(s.
width(), s.
height());
00396 }
00397
00398
void KHTMLView::clear()
00399 {
00400
00401
setStaticBackground(
true);
00402
#ifndef KHTML_NO_CARET
00403
if (!m_part->
isCaretMode() && !m_part->
isEditable()) caretOff();
00404
#endif
00405
00406 d->reset();
00407 killTimers();
00408 emit cleared();
00409
00410
QScrollView::setHScrollBarMode(d->hmode);
00411
QScrollView::setVScrollBarMode(d->vmode);
00412 }
00413
00414
void KHTMLView::hideEvent(
QHideEvent* e)
00415 {
00416 QScrollView::hideEvent(e);
00417 }
00418
00419
void KHTMLView::showEvent(
QShowEvent* e)
00420 {
00421 QScrollView::showEvent(e);
00422 }
00423
00424
void KHTMLView::resizeEvent (
QResizeEvent* e)
00425 {
00426 QScrollView::resizeEvent(e);
00427
00428
if ( m_part && m_part->
xmlDocImpl() )
00429 m_part->
xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT,
false,
false );
00430 }
00431
00432
void KHTMLView::viewportResizeEvent (
QResizeEvent* e)
00433 {
00434
QScrollView::viewportResizeEvent(e);
00435
00436
00437
00438
00439
if (d->layoutSchedulingEnabled)
00440
layout();
00441
#ifndef KHTML_NO_CARET
00442
else {
00443 hideCaret();
00444 recalcAndStoreCaretPos();
00445 showCaret();
00446 }
00447
#endif
00448
00449
KApplication::sendPostedEvents(
viewport(), QEvent::Paint);
00450 }
00451
00452
00453
void KHTMLView::drawContents(
QPainter*)
00454 {
00455 }
00456
00457
void KHTMLView::drawContents(
QPainter *p,
int ex,
int ey,
int ew,
int eh )
00458 {
00459
#ifdef DEBUG_PIXEL
00460
00461
if ( d->timer.elapsed() > 5000 ) {
00462 qDebug(
"drawed %d pixels in %d repaints the last %d milliseconds",
00463 d->pixelbooth, d->repaintbooth, d->timer.elapsed() );
00464 d->timer.restart();
00465 d->pixelbooth = 0;
00466 d->repaintbooth = 0;
00467 }
00468 d->pixelbooth += ew*eh;
00469 d->repaintbooth++;
00470
#endif
00471
00472
00473
if(!m_part || !m_part->
xmlDocImpl() || !m_part->
xmlDocImpl()->renderer()) {
00474 p->
fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00475
return;
00476 }
00477
00478
QPoint pt =
contentsToViewport(
QPoint(ex, ey));
00479
QRegion cr =
QRect(pt.
x(), pt.
y(), ew, eh);
00480
00481
for (
QPtrDictIterator<QWidget> it(d->visibleWidgets); it.current(); ++it) {
00482
QWidget *w = it.current();
00483 RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
00484
QScrollView *sv = ::qt_cast<QScrollView *>(w);
00485
if (sv || !rw->isFormElement()) {
00486
00487
int x, y;
00488 rw->absolutePosition(x, y);
00489
contentsToViewport(x, y, x, y);
00490 cr -=
QRect(x, y, rw->width(), rw->height());
00491 }
00492 }
00493
00494
#if 0
00495
00496
00497
if (cr.
isEmpty())
00498
return;
00499
#endif
00500
00501
#ifndef DEBUG_NO_PAINT_BUFFER
00502
p->
setClipRegion(cr);
00503
00504
if (eh > PAINT_BUFFER_HEIGHT && ew <= 10) {
00505
if ( d->vertPaintBuffer->height() <
visibleHeight() )
00506 d->vertPaintBuffer->resize(10,
visibleHeight());
00507 d->tp->begin(d->vertPaintBuffer);
00508 d->tp->translate(-ex, -ey);
00509 d->tp->fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00510 m_part->
xmlDocImpl()->renderer()->layer()->paint(d->tp,
QRect(ex, ey, ew, eh));
00511 d->tp->end();
00512 p->
drawPixmap(ex, ey, *d->vertPaintBuffer, 0, 0, ew, eh);
00513 }
00514
else {
00515
if ( d->paintBuffer->width() <
visibleWidth() )
00516 d->paintBuffer->resize(
visibleWidth(),PAINT_BUFFER_HEIGHT);
00517
00518
int py=0;
00519
while (py < eh) {
00520
int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;
00521 d->tp->begin(d->paintBuffer);
00522 d->tp->translate(-ex, -ey-py);
00523 d->tp->fillRect(ex, ey+py, ew, ph, palette().active().brush(QColorGroup::Base));
00524 m_part->
xmlDocImpl()->renderer()->layer()->paint(d->tp,
QRect(ex, ey+py, ew, ph));
00525 d->tp->end();
00526
00527 p->
drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph);
00528 py += PAINT_BUFFER_HEIGHT;
00529 }
00530 }
00531
#else // !DEBUG_NO_PAINT_BUFFER
00532
static int cnt=0;
00533 ex =
contentsX(); ey =
contentsY();
00534 ew =
visibleWidth(); eh =
visibleHeight();
00535
QRect pr(ex,ey,ew,eh);
00536
kdDebug() <<
"[" << ++cnt <<
"]" <<
" clip region: " << pr <<
endl;
00537
00538
00539 p->
fillRect(ex, ey, ew, eh, palette().active().brush(QColorGroup::Base));
00540 m_part->
xmlDocImpl()->renderer()->layer()->paint(p, pr);
00541
#endif // DEBUG_NO_PAINT_BUFFER
00542
00543
#ifndef KHTML_NO_CARET
00544
if (d->m_caretViewContext && d->m_caretViewContext->visible) {
00545
QRect pos(d->m_caretViewContext->x, d->m_caretViewContext->y,
00546 d->m_caretViewContext->width, d->m_caretViewContext->height);
00547
if (pos.intersects(
QRect(ex, ey, ew, eh))) {
00548 p->
setRasterOp(XorROP);
00549 p->
setPen(white);
00550
if (pos.width() == 1)
00551 p->
drawLine(pos.topLeft(), pos.bottomRight());
00552
else {
00553 p->
fillRect(pos, white);
00554 }
00555 }
00556 }
00557
#endif // KHTML_NO_CARET
00558
00559
00560
00561
00562 khtml::DrawContentsEvent
event( p, ex, ey, ew, eh );
00563
QApplication::sendEvent( m_part, &event );
00564
00565 }
00566
00567 void KHTMLView::setMarginWidth(
int w)
00568 {
00569
00570 _marginWidth = w;
00571 }
00572
00573
void KHTMLView::setMarginHeight(
int h)
00574 {
00575
00576 _marginHeight = h;
00577 }
00578
00579 void KHTMLView::layout()
00580 {
00581
if( m_part && m_part->
xmlDocImpl() ) {
00582 DOM::DocumentImpl *document = m_part->
xmlDocImpl();
00583
00584 khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer());
00585
if ( !root )
return;
00586
00587 d->layoutSchedulingEnabled=
false;
00588
00589
if (document->isHTMLDocument()) {
00590 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
00591
if(body && body->renderer() && body->id() == ID_FRAMESET) {
00592
QScrollView::setVScrollBarMode(AlwaysOff);
00593
QScrollView::setHScrollBarMode(AlwaysOff);
00594 body->renderer()->setLayouted(
false);
00595
00596
00597
00598
00599 }
00600
else if (!d->tooltip)
00601 d->tooltip =
new KHTMLToolTip(
this, d );
00602 }
00603
00604 _height =
visibleHeight();
00605 _width =
visibleWidth();
00606
00607
00608 root->setMinMaxKnown(
false);
00609 root->setLayouted(
false);
00610 root->layout();
00611
00612 emit finishedLayout();
00613
#ifndef KHTML_NO_CARET
00614
hideCaret();
00615
if ((m_part->
isCaretMode() || m_part->
isEditable())
00616 && !d->complete && d->m_caretViewContext
00617 && !d->m_caretViewContext->caretMoved) {
00618 initCaret();
00619 }
else {
00620 recalcAndStoreCaretPos();
00621 showCaret();
00622 }
00623
#endif
00624
root->repaint();
00625
00626 }
00627
else
00628 _width =
visibleWidth();
00629
00630 killTimer(d->layoutTimerId);
00631 d->layoutTimerId = 0;
00632 d->layoutSchedulingEnabled=
true;
00633 }
00634
00635
void KHTMLView::closeChildDialogs()
00636 {
00637
QObjectList *dlgs = queryList(
"QDialog");
00638
for (
QObject *dlg = dlgs->first(); dlg; dlg = dlgs->next())
00639 {
00640
KDialogBase* dlgbase = dynamic_cast<KDialogBase *>( dlg );
00641
if ( dlgbase ) {
00642
kdDebug(6000) <<
"closeChildDialogs: closing dialog " << dlgbase <<
endl;
00643
00644
00645 dlgbase->
cancel();
00646 }
00647
else
00648 {
00649
kdWarning() <<
"closeChildDialogs: not a KDialogBase! Don't use QDialogs in KDE! " << static_cast<QWidget*>(dlg) <<
endl;
00650 static_cast<QWidget*>(dlg)->hide();
00651 }
00652 }
00653
delete dlgs;
00654 d->m_dialogsAllowed =
false;
00655 }
00656
00657
bool KHTMLView::dialogsAllowed() {
00658
bool allowed = d->m_dialogsAllowed;
00659
KHTMLPart* p = m_part->
parentPart();
00660
if (p && p->
view())
00661 allowed &= p->
view()->
dialogsAllowed();
00662
return allowed;
00663 }
00664
00665
void KHTMLView::closeEvent(
QCloseEvent* ev )
00666 {
00667 closeChildDialogs();
00668 QScrollView::closeEvent( ev );
00669 }
00670
00671
00672
00673
00675
00676
void KHTMLView::viewportMousePressEvent(
QMouseEvent *_mouse )
00677 {
00678
if(!m_part->
xmlDocImpl())
return;
00679
if (d->possibleTripleClick)
00680 {
00681 viewportMouseDoubleClickEvent( _mouse );
00682
return;
00683 }
00684
00685
int xm, ym;
00686
viewportToContents(_mouse->
x(), _mouse->
y(), xm, ym);
00687
00688
00689
00690 d->isDoubleClick =
false;
00691
00692 DOM::NodeImpl::MouseEvent mev( _mouse->
stateAfter(), DOM::NodeImpl::MousePress );
00693 m_part->
xmlDocImpl()->prepareMouseEvent(
false, xm, ym, &mev );
00694
00695
if (d->clickCount > 0 &&
00696
QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <=
QApplication::startDragDistance())
00697 d->clickCount++;
00698
else {
00699 d->clickCount = 1;
00700 d->clickX = xm;
00701 d->clickY = ym;
00702 }
00703
00704
bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),
true,
00705 d->clickCount,_mouse,
true,DOM::NodeImpl::MousePress);
00706
00707 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
00708
if (r && r->isWidget())
00709 _mouse->
ignore();
00710
00711
if (!swallowEvent) {
00712 emit m_part->
nodeActivated(mev.innerNode);
00713
00714 khtml::MousePressEvent
event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
00715
QApplication::sendEvent( m_part, &event );
00716
00717 }
00718 }
00719
00720
void KHTMLView::viewportMouseDoubleClickEvent(
QMouseEvent *_mouse )
00721 {
00722
if(!m_part->
xmlDocImpl())
return;
00723
00724
int xm, ym;
00725
viewportToContents(_mouse->
x(), _mouse->
y(), xm, ym);
00726
00727
kdDebug( 6000 ) <<
"mouseDblClickEvent: x=" << xm <<
", y=" << ym <<
endl;
00728
00729 d->isDoubleClick =
true;
00730
00731 DOM::NodeImpl::MouseEvent mev( _mouse->
stateAfter(), DOM::NodeImpl::MouseDblClick );
00732 m_part->
xmlDocImpl()->prepareMouseEvent(
false, xm, ym, &mev );
00733
00734
00735
00736
if (d->clickCount > 0 &&
00737
QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <=
QApplication::startDragDistance())
00738 d->clickCount++;
00739
else {
00740 d->clickCount = 1;
00741 d->clickX = xm;
00742 d->clickY = ym;
00743 }
00744
bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),
true,
00745 d->clickCount,_mouse,
true,DOM::NodeImpl::MouseDblClick);
00746
00747 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
00748
if (r && r->isWidget())
00749 _mouse->
ignore();
00750
00751
if (!swallowEvent) {
00752 khtml::MouseDoubleClickEvent
event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode, d->clickCount );
00753
QApplication::sendEvent( m_part, &event );
00754 }
00755
00756 d->possibleTripleClick=
true;
00757
QTimer::singleShot(QApplication::doubleClickInterval(),
this,SLOT(tripleClickTimeout()));
00758 }
00759
00760
void KHTMLView::tripleClickTimeout()
00761 {
00762 d->possibleTripleClick =
false;
00763 d->clickCount = 0;
00764 }
00765
00766
static inline void forwardPeripheralEvent(khtml::RenderWidget* r,
QMouseEvent* me,
int x,
int y)
00767 {
00768
int absx = 0;
00769
int absy = 0;
00770 r->absolutePosition(absx, absy);
00771
QPoint p(x-absx, y-absy);
00772
QMouseEvent fw(me->type(), p, me->
button(), me->
state());
00773
QWidget* w = r->widget();
00774
if(w)
00775 static_cast<khtml::RenderWidget::EventPropagator*>(w)->sendEvent(&fw);
00776 }
00777
00778
void KHTMLView::viewportMouseMoveEvent(
QMouseEvent * _mouse )
00779 {
00780
00781
if(!m_part->
xmlDocImpl())
return;
00782
00783
int xm, ym;
00784
viewportToContents(_mouse->
x(), _mouse->
y(), xm, ym);
00785
00786 DOM::NodeImpl::MouseEvent mev( _mouse->
stateAfter(), DOM::NodeImpl::MouseMove );
00787
00788 m_part->
xmlDocImpl()->prepareMouseEvent( _mouse->
state() & Qt::MouseButtonMask , xm, ym, &mev );
00789
00790
00791
00792
00793
00794
bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,mev.innerNode.handle(),
false,
00795 0,_mouse,
true,DOM::NodeImpl::MouseMove);
00796
00797
if (d->clickCount > 0 &&
00798
QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() >
QApplication::startDragDistance()) {
00799 d->clickCount = 0;
00800 }
00801
00802
00803 m_part->
executeScheduledScript();
00804
00805 DOM::NodeImpl* fn = m_part->
xmlDocImpl()->focusNode();
00806
if (fn && fn != mev.innerNode.handle() &&
00807 fn->renderer() && fn->renderer()->isWidget()) {
00808 forwardPeripheralEvent(static_cast<khtml::RenderWidget*>(fn->renderer()), _mouse, xm, ym);
00809 }
00810
00811 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
00812 khtml::RenderStyle* style = (r && r->style()) ? r->style() : 0;
00813
QCursor c;
00814
switch ( style ? style->cursor() : CURSOR_AUTO) {
00815
case CURSOR_AUTO:
00816
if ( r && r->isText() )
00817 c =
KCursor::ibeamCursor();
00818
00819
if ( mev.url.length() && m_part->
settings()->
changeCursor() )
00820 c = m_part->
urlCursor();
00821
00822
if (r && r->isFrameSet() && !static_cast<RenderFrameSet*>(r)->noResize())
00823 c =
QCursor(static_cast<RenderFrameSet*>(r)->cursorShape());
00824
00825
break;
00826
case CURSOR_CROSS:
00827 c =
KCursor::crossCursor();
00828
break;
00829
case CURSOR_POINTER:
00830 c = m_part->
urlCursor();
00831
break;
00832
case CURSOR_PROGRESS:
00833 c =
KCursor::workingCursor();
00834
break;
00835
case CURSOR_MOVE:
00836 c =
KCursor::sizeAllCursor();
00837
break;
00838
case CURSOR_E_RESIZE:
00839
case CURSOR_W_RESIZE:
00840 c =
KCursor::sizeHorCursor();
00841
break;
00842
case CURSOR_N_RESIZE:
00843
case CURSOR_S_RESIZE:
00844 c =
KCursor::sizeVerCursor();
00845
break;
00846
case CURSOR_NE_RESIZE:
00847
case CURSOR_SW_RESIZE:
00848 c =
KCursor::sizeBDiagCursor();
00849
break;
00850
case CURSOR_NW_RESIZE:
00851
case CURSOR_SE_RESIZE:
00852 c =
KCursor::sizeFDiagCursor();
00853
break;
00854
case CURSOR_TEXT:
00855 c =
KCursor::ibeamCursor();
00856
break;
00857
case CURSOR_WAIT:
00858 c =
KCursor::waitCursor();
00859
break;
00860
case CURSOR_HELP:
00861 c =
KCursor::whatsThisCursor();
00862
break;
00863
case CURSOR_DEFAULT:
00864
break;
00865 }
00866
00867
if (
viewport()->cursor().handle() != c.
handle() ) {
00868
if( c.
handle() ==
KCursor::arrowCursor().
handle()) {
00869
for (
KHTMLPart* p = m_part; p; p = p->
parentPart())
00870 p->
view()->
viewport()->unsetCursor();
00871 }
00872
else {
00873
viewport()->setCursor( c );
00874 }
00875 }
00876
if (r && r->isWidget()) {
00877 _mouse->
ignore();
00878 }
00879
00880
00881 d->prevMouseX = xm;
00882 d->prevMouseY = ym;
00883
00884
if (!swallowEvent) {
00885 khtml::MouseMoveEvent
event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
00886
QApplication::sendEvent( m_part, &event );
00887 }
00888 }
00889
00890
void KHTMLView::viewportMouseReleaseEvent(
QMouseEvent * _mouse )
00891 {
00892
if ( !m_part->
xmlDocImpl() )
return;
00893
00894
int xm, ym;
00895
viewportToContents(_mouse->
x(), _mouse->
y(), xm, ym);
00896
00897 DOM::NodeImpl::MouseEvent mev( _mouse->
stateAfter(), DOM::NodeImpl::MouseRelease );
00898 m_part->
xmlDocImpl()->prepareMouseEvent(
false, xm, ym, &mev );
00899
00900
bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,mev.innerNode.handle(),
true,
00901 d->clickCount,_mouse,
false,DOM::NodeImpl::MouseRelease);
00902
00903
if (d->clickCount > 0 &&
00904
QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <=
QApplication::startDragDistance()) {
00905
QMouseEvent me(d->isDoubleClick ? QEvent::MouseButtonDblClick : QEvent::MouseButtonRelease,
00906 _mouse->
pos(), _mouse->
button(), _mouse->
state());
00907 dispatchMouseEvent(EventImpl::CLICK_EVENT, mev.innerNode.handle(),
true,
00908 d->clickCount, &me,
true, DOM::NodeImpl::MouseRelease);
00909 }
00910
00911 DOM::NodeImpl* fn = m_part->
xmlDocImpl()->focusNode();
00912
if (fn && fn != mev.innerNode.handle() &&
00913 fn->renderer() && fn->renderer()->isWidget()) {
00914 forwardPeripheralEvent(static_cast<khtml::RenderWidget*>(fn->renderer()), _mouse, xm, ym);
00915 }
00916
00917 khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
00918
if (r && r->isWidget())
00919 _mouse->
ignore();
00920
00921
if (!swallowEvent) {
00922 khtml::MouseReleaseEvent
event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
00923
QApplication::sendEvent( m_part, &event );
00924 }
00925 }
00926
00927
00928
bool KHTMLView::dispatchKeyEvent(
QKeyEvent *_ke )
00929 {
00930
if (!m_part->
xmlDocImpl())
00931
return false;
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
if( _ke == d->postponed_autorepeat )
00953 {
00954
return false;
00955 }
00956
00957
if( _ke->type() == QEvent::KeyPress )
00958 {
00959
if( !_ke->
isAutoRepeat())
00960 {
00961
bool ret = dispatchKeyEventHelper( _ke,
false );
00962
if( dispatchKeyEventHelper( _ke,
true ))
00963 ret =
true;
00964
return ret;
00965 }
00966
else
00967 {
00968
bool ret = dispatchKeyEventHelper( _ke,
true );
00969
if( !ret && d->postponed_autorepeat )
00970 keyPressEvent( d->postponed_autorepeat );
00971
delete d->postponed_autorepeat;
00972 d->postponed_autorepeat = NULL;
00973
return ret;
00974 }
00975 }
00976
else
00977 {
00978
00979
00980
if ( d->postponed_autorepeat ) {
00981
delete d->postponed_autorepeat;
00982 d->postponed_autorepeat = 0;
00983 }
00984
00985
if( !_ke->
isAutoRepeat()) {
00986
return dispatchKeyEventHelper( _ke,
false );
00987 }
00988
else
00989 {
00990 d->postponed_autorepeat =
new QKeyEvent( _ke->type(), _ke->
key(), _ke->
ascii(), _ke->
state(),
00991 _ke->
text(), _ke->
isAutoRepeat(), _ke->
count());
00992
if( _ke->
isAccepted())
00993 d->postponed_autorepeat->accept();
00994
else
00995 d->postponed_autorepeat->ignore();
00996
return true;
00997 }
00998 }
00999 }
01000
01001
01002
bool KHTMLView::dispatchKeyEventHelper(
QKeyEvent *_ke,
bool keypress )
01003 {
01004 DOM::NodeImpl* keyNode = m_part->
xmlDocImpl()->focusNode();
01005
if (keyNode) {
01006
return keyNode->dispatchKeyEvent(_ke, keypress);
01007 }
else {
01008
return m_part->
xmlDocImpl()->dispatchKeyEvent(_ke, keypress);
01009 }
01010 }
01011
01012
void KHTMLView::keyPressEvent(
QKeyEvent *_ke )
01013 {
01014
01015
#ifndef KHTML_NO_CARET
01016
if (m_part->
isEditable() || m_part->
isCaretMode()
01017 || (m_part->
xmlDocImpl() && m_part->
xmlDocImpl()->focusNode()
01018 && m_part->
xmlDocImpl()->focusNode()->contentEditable())) {
01019 d->caretViewContext()->keyReleasePending =
true;
01020 caretKeyPressEvent(_ke);
01021
return;
01022 }
01023
#endif // KHTML_NO_CARET
01024
01025
01026
01027
if( handleAccessKey( _ke )) {
01028 _ke->
accept();
01029
return;
01030 }
01031
01032
if ( dispatchKeyEvent( _ke )) {
01033
01034 _ke->
accept();
01035
return;
01036 }
01037
01038
int offs = (
clipper()->height() < 30) ?
clipper()->height() : 30;
01039
if (_ke->
state() & Qt::ShiftButton)
01040
switch(_ke->
key())
01041 {
01042
case Key_Space:
01043
if ( d->vmode == QScrollView::AlwaysOff )
01044 _ke->
accept();
01045
else {
01046
scrollBy( 0, -
clipper()->height() - offs );
01047
if(d->scrollSuspended)
01048 d->newScrollTimer(
this, 0);
01049 }
01050
break;
01051
01052
case Key_Down:
01053
case Key_J:
01054 d->adjustScroller(
this, KHTMLViewPrivate::ScrollDown, KHTMLViewPrivate::ScrollUp);
01055
break;
01056
01057
case Key_Up:
01058
case Key_K:
01059 d->adjustScroller(
this, KHTMLViewPrivate::ScrollUp, KHTMLViewPrivate::ScrollDown);
01060
break;
01061
01062
case Key_Left:
01063
case Key_H:
01064 d->adjustScroller(
this, KHTMLViewPrivate::ScrollLeft, KHTMLViewPrivate::ScrollRight);
01065
break;
01066
01067
case Key_Right:
01068
case Key_L:
01069 d->adjustScroller(
this, KHTMLViewPrivate::ScrollRight, KHTMLViewPrivate::ScrollLeft);
01070
break;
01071 }
01072
else
01073
switch ( _ke->
key() )
01074 {
01075
case Key_Down:
01076
case Key_J:
01077
if ( d->vmode == QScrollView::AlwaysOff )
01078 _ke->
accept();
01079
else {
01080
if (!d->scrollTimerId || d->scrollSuspended)
01081
scrollBy( 0, 10 );
01082
if (d->scrollTimerId)
01083 d->newScrollTimer(
this, 0);
01084 }
01085
break;
01086
01087
case Key_Space:
01088
case Key_Next:
01089
if ( d->vmode == QScrollView::AlwaysOff )
01090 _ke->
accept();
01091
else {
01092
scrollBy( 0,
clipper()->height() - offs );
01093
if(d->scrollSuspended)
01094 d->newScrollTimer(
this, 0);
01095 }
01096
break;
01097
01098
case Key_Up:
01099
case Key_K:
01100
if ( d->vmode == QScrollView::AlwaysOff )
01101 _ke->
accept();
01102
else {
01103
if (!d->scrollTimerId || d->scrollSuspended)
01104
scrollBy( 0, -10 );
01105
if (d->scrollTimerId)
01106 d->newScrollTimer(
this, 0);
01107 }
01108
break;
01109
01110
case Key_Prior:
01111
if ( d->vmode == QScrollView::AlwaysOff )
01112 _ke->
accept();
01113
else {
01114
scrollBy( 0, -
clipper()->height() + offs );
01115
if(d->scrollSuspended)
01116 d->newScrollTimer(
this, 0);
01117 }
01118
break;
01119
case Key_Right:
01120
case Key_L:
01121
if ( d->hmode == QScrollView::AlwaysOff )
01122 _ke->
accept();
01123
else {
01124
if (!d->scrollTimerId || d->scrollSuspended)
01125
scrollBy( 10, 0 );
01126
if (d->scrollTimerId)
01127 d->newScrollTimer(
this, 0);
01128 }
01129
break;
01130
case Key_Left:
01131
case Key_H:
01132
if ( d->hmode == QScrollView::AlwaysOff )
01133 _ke->
accept();
01134
else {
01135
if (!d->scrollTimerId || d->scrollSuspended)
01136
scrollBy( -10, 0 );
01137
if (d->scrollTimerId)
01138 d->newScrollTimer(
this, 0);
01139 }
01140
break;
01141
case Key_Enter:
01142
case Key_Return:
01143
01144
01145
if (m_part->
xmlDocImpl()) {
01146 NodeImpl *n = m_part->
xmlDocImpl()->focusNode();
01147
if (n)
01148 n->setActive();
01149 d->originalNode = n;
01150 }
01151
break;
01152
case Key_Home:
01153
if ( d->vmode == QScrollView::AlwaysOff )
01154 _ke->
accept();
01155
else {
01156
setContentsPos( 0, 0 );
01157
if(d->scrollSuspended)
01158 d->newScrollTimer(
this, 0);
01159 }
01160
break;
01161
case Key_End:
01162
if ( d->vmode == QScrollView::AlwaysOff )
01163 _ke->
accept();
01164
else {
01165
setContentsPos( 0,
contentsHeight() -
visibleHeight() );
01166
if(d->scrollSuspended)
01167 d->newScrollTimer(
this, 0);
01168 }
01169
break;
01170
case Key_Shift:
01171
01172 _ke->
ignore();
01173
return;
01174
case Key_Control:
01175
if (d->scrollTimerId)
01176 d->scrollSuspended = !d->scrollSuspended;
01177
break;
01178
default:
01179
if (d->scrollTimerId)
01180 d->newScrollTimer(
this, 0);
01181 _ke->
ignore();
01182
return;
01183 }
01184 _ke->
accept();
01185 }
01186
01187
void KHTMLView::keyReleaseEvent(
QKeyEvent *_ke)
01188 {
01189
if (d->m_caretViewContext && d->m_caretViewContext->keyReleasePending) {
01190
01191 d->m_caretViewContext->keyReleasePending =
false;
01192
return;
01193 }
01194
01195
01196
if ( dispatchKeyEvent( _ke ) )
01197 {
01198 _ke->
accept();
01199
return;
01200 }
01201 QScrollView::keyReleaseEvent(_ke);
01202 }
01203
01204
void KHTMLView::contentsContextMenuEvent (
QContextMenuEvent * )
01205 {
01206
01207
#if 0
01208
if (!m_part->
xmlDocImpl())
return;
01209
int xm = _ce->x();
01210
int ym = _ce->y();
01211
01212 DOM::NodeImpl::MouseEvent mev( _ce->state(), DOM::NodeImpl::MouseMove );
01213 m_part->
xmlDocImpl()->prepareMouseEvent( xm, ym, &mev );
01214
01215 NodeImpl *targetNode = mev.innerNode.handle();
01216
if (targetNode && targetNode->renderer() && targetNode->renderer()->isWidget()) {
01217
int absx = 0;
01218
int absy = 0;
01219 targetNode->renderer()->absolutePosition(absx,absy);
01220
QPoint pos(xm-absx,ym-absy);
01221
01222
QWidget *w = static_cast<RenderWidget*>(targetNode->renderer())->widget();
01223
QContextMenuEvent cme(_ce->reason(),pos,_ce->globalPos(),_ce->state());
01224 setIgnoreEvents(
true);
01225
QApplication::sendEvent(w,&cme);
01226 setIgnoreEvents(
false);
01227 }
01228
#endif
01229
}
01230
01231
bool KHTMLView::focusNextPrevChild(
bool next )
01232 {
01233
01234
if (m_part->
xmlDocImpl()) {
01235 focusNextPrevNode(next);
01236
if (m_part->
xmlDocImpl()->focusNode() != 0) {
01237
kdDebug() <<
"focusNode.name: "
01238 << m_part->
xmlDocImpl()->focusNode()->nodeName().string() <<
endl;
01239
return true;
01240 }
01241 }
01242
01243
01244
if (m_part->
parentPart() && m_part->
parentPart()->
view())
01245
return m_part->
parentPart()->
view()->
focusNextPrevChild(next);
01246
01247
return QWidget::focusNextPrevChild(next);
01248 }
01249
01250
void KHTMLView::doAutoScroll()
01251 {
01252
QPoint pos =
QCursor::pos();
01253 pos =
viewport()->mapFromGlobal( pos );
01254
01255
int xm, ym;
01256
viewportToContents(pos.
x(), pos.
y(), xm, ym);
01257
01258 pos =
QPoint(pos.
x() -
viewport()->x(), pos.
y() -
viewport()->y());
01259
if ( (pos.
y() < 0) || (pos.
y() >
visibleHeight()) ||
01260 (pos.
x() < 0) || (pos.
x() >
visibleWidth()) )
01261 {
01262
ensureVisible( xm, ym, 0, 5 );
01263
01264
#ifndef KHTML_NO_SELECTION
01265
01266
DOM::Node innerNode;
01267
if (m_part->
isExtendingSelection()) {
01268 RenderObject::NodeInfo renderInfo(
true,
false);
01269 m_part->
xmlDocImpl()->renderer()->layer()
01270 ->nodeAtPoint(renderInfo, xm, ym);
01271 innerNode = renderInfo.innerNode();
01272 }
01273
01274
if (innerNode.
handle() && innerNode.
handle()->renderer()) {
01275
int absX, absY;
01276 innerNode.
handle()->renderer()->absolutePosition(absX, absY);
01277
01278 m_part->
extendSelectionTo(xm, ym, absX, absY, innerNode);
01279 }
01280
#endif // KHTML_NO_SELECTION
01281
}
01282 }
01283
01284
01285
class HackWidget :
public QWidget
01286 {
01287
public:
01288
inline void setNoErase() {
setWFlags(
getWFlags()|WRepaintNoErase); }
01289 };
01290
01291
bool KHTMLView::eventFilter(
QObject *o,
QEvent *e)
01292 {
01293
if ( e->
type() == QEvent::AccelOverride ) {
01294
QKeyEvent* ke = (
QKeyEvent*) e;
01295
01296
if (m_part->
isEditable() || m_part->
isCaretMode()
01297 || (m_part->
xmlDocImpl() && m_part->
xmlDocImpl()->focusNode()
01298 && m_part->
xmlDocImpl()->focusNode()->contentEditable())) {
01299
01300
if ( (ke->
state() & ControlButton) || (ke->
state() & ShiftButton) ) {
01301
switch ( ke->
key() ) {
01302
case Key_Left:
01303
case Key_Right:
01304
case Key_Up:
01305
case Key_Down:
01306
case Key_Home:
01307
case Key_End:
01308 ke->
accept();
01309
01310
return true;
01311
default:
01312
break;
01313 }
01314 }
01315 }
01316 }
01317
01318
QWidget *view =
viewport();
01319
01320
if (o == view) {
01321
01322
01323
if(e->
type() == QEvent::ChildInserted) {
01324
QObject *c = static_cast<QChildEvent *>(e)->child();
01325
if (c->
isWidgetType()) {
01326
QWidget *w = static_cast<QWidget *>(c);
01327
01328
if (w->
parentWidget(
true) == view) {
01329
if (!strcmp(w->name(),
"__khtml")) {
01330 w->installEventFilter(
this);
01331 w->
unsetCursor();
01332 w->
setBackgroundMode( QWidget::NoBackground );
01333 static_cast<HackWidget *>(w)->setNoErase();
01334
if (w->children()) {
01335
QObjectListIterator it(*w->children());
01336
for (; it.current(); ++it) {
01337
QWidget *widget = ::qt_cast<QWidget *>(it.current());
01338
if (widget && !widget->
isTopLevel()
01339 && !::qt_cast<QScrollView *>(widget)) {
01340 widget->
setBackgroundMode( QWidget::NoBackground );
01341 static_cast<HackWidget *>(widget)->setNoErase();
01342 widget->installEventFilter(
this);
01343 }
01344 }
01345 }
01346 }
01347 }
01348 }
01349 }
01350 }
else if (o->
isWidgetType()) {
01351
QWidget *v = static_cast<QWidget *>(o);
01352
QWidget *c = v;
01353
while (v && v != view) {
01354 c = v;
01355 v = v->
parentWidget(
true);
01356 }
01357
01358
if (v && !strcmp(c->name(),
"__khtml")) {
01359
bool block =
false;
01360
QWidget *w = static_cast<QWidget *>(o);
01361
switch(e->
type()) {
01362
case QEvent::Paint:
01363
if (!allowWidgetPaintEvents) {
01364
01365
01366 block =
true;
01367
int x = 0, y = 0;
01368
QWidget *v = w;
01369
while (v && v != view) {
01370 x += v->
x();
01371 y += v->
y();
01372 v = v->
parentWidget();
01373 }
01374
viewportToContents( x, y, x, y );
01375
QPaintEvent *pe = static_cast<QPaintEvent *>(e);
01376 scheduleRepaint(x + pe->
rect().x(), y + pe->
rect().y(),
01377 pe->
rect().width(), pe->
rect().height());
01378 }
01379
break;
01380
case QEvent::MouseMove:
01381
case QEvent::MouseButtonPress:
01382
case QEvent::MouseButtonRelease:
01383
case QEvent::MouseButtonDblClick: {
01384
if (w->
parentWidget() == view && !::qt_cast<QScrollBar *>(w)) {
01385
QMouseEvent *me = static_cast<QMouseEvent *>(e);
01386
QPoint pt = (me->
pos() + w->
pos());
01387
QMouseEvent me2(me->type(), pt, me->
button(), me->
state());
01388
01389
if (e->
type() == QEvent::MouseMove)
01390 viewportMouseMoveEvent(&me2);
01391
else if(e->
type() == QEvent::MouseButtonPress)
01392 viewportMousePressEvent(&me2);
01393
else if(e->
type() == QEvent::MouseButtonRelease)
01394 viewportMouseReleaseEvent(&me2);
01395
else
01396 viewportMouseDoubleClickEvent(&me2);
01397 block =
true;
01398 }
01399
break;
01400 }
01401
case QEvent::KeyPress:
01402
case QEvent::KeyRelease:
01403
if (w->
parentWidget() == view && !::qt_cast<QScrollBar *>(w)) {
01404
QKeyEvent *ke = static_cast<QKeyEvent *>(e);
01405
if (e->
type() == QEvent::KeyPress)
01406 keyPressEvent(ke);
01407
else
01408 keyReleaseEvent(ke);
01409 block =
true;
01410 }
01411
default:
01412
break;
01413 }
01414
if (block) {
01415
01416
return true;
01417 }
01418 }
01419 }
01420
01421
01422
return QScrollView::eventFilter(o, e);
01423 }
01424
01425
01426 DOM::NodeImpl *KHTMLView::nodeUnderMouse()
const
01427
{
01428
return d->underMouse;
01429 }
01430
01431
bool KHTMLView::scrollTo(
const QRect &bounds)
01432 {
01433 d->scrollingSelf =
true;
01434
01435
int x, y, xe, ye;
01436 x = bounds.
left();
01437 y = bounds.
top();
01438 xe = bounds.
right();
01439 ye = bounds.
bottom();
01440
01441
01442
01443
int deltax;
01444
int deltay;
01445
01446
int curHeight =
visibleHeight();
01447
int curWidth =
visibleWidth();
01448
01449
if (ye-y>curHeight-d->borderY)
01450 ye = y + curHeight - d->borderY;
01451
01452
if (xe-x>curWidth-d->borderX)
01453 xe = x + curWidth - d->borderX;
01454
01455
01456
if (x <
contentsX() + d->borderX )
01457 deltax = x -
contentsX() - d->borderX;
01458
01459
else if (xe + d->borderX >
contentsX() + curWidth)
01460 deltax = xe + d->borderX - (
contentsX() + curWidth );
01461
else
01462 deltax = 0;
01463
01464
01465
if (y <
contentsY() + d->borderY)
01466 deltay = y -
contentsY() - d->borderY;
01467
01468
else if (ye + d->borderY >
contentsY() + curHeight)
01469 deltay = ye + d->borderY - (
contentsY() + curHeight );
01470
else
01471 deltay = 0;
01472
01473
int maxx = curWidth-d->borderX;
01474
int maxy = curHeight-d->borderY;
01475
01476
int scrollX,scrollY;
01477
01478 scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax>-maxx ? deltax : -maxx);
01479 scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay>-maxy ? deltay : -maxy);
01480
01481
if (
contentsX() + scrollX < 0)
01482 scrollX = -
contentsX();
01483
else if (
contentsWidth() -
visibleWidth() -
contentsX() < scrollX)
01484 scrollX =
contentsWidth() -
visibleWidth() -
contentsX();
01485
01486
if (
contentsY() + scrollY < 0)
01487 scrollY = -
contentsY();
01488
else if (
contentsHeight() -
visibleHeight() -
contentsY() < scrollY)
01489 scrollY =
contentsHeight() -
visibleHeight() -
contentsY();
01490
01491
scrollBy(scrollX, scrollY);
01492
01493
01494
01495
01496
if (scrollX<0)
01497 scrollX=-scrollX;
01498
if (scrollY<0)
01499 scrollY=-scrollY;
01500
01501 d->scrollingSelf =
false;
01502
01503
if ( (scrollX!=maxx) && (scrollY!=maxy) )
01504
return true;
01505
else return false;
01506
01507 }
01508
01509
void KHTMLView::focusNextPrevNode(
bool next)
01510 {
01511
01512
01513
01514
01515
01516 DocumentImpl *doc = m_part->
xmlDocImpl();
01517 NodeImpl *oldFocusNode = doc->focusNode();
01518 NodeImpl *newFocusNode;
01519
01520
01521
if (
next)
01522 newFocusNode = doc->nextFocusNode(oldFocusNode);
01523
else
01524 newFocusNode = doc->previousFocusNode(oldFocusNode);
01525
01526
01527
01528
if (!oldFocusNode && newFocusNode && d->scrollBarMoved) {
01529
01530
kdDebug(6000) <<
" searching for visible link" <<
endl;
01531
01532
bool visible =
false;
01533 NodeImpl *toFocus = newFocusNode;
01534
while (!visible && toFocus) {
01535
QRect focusNodeRect = toFocus->getRect();
01536
if ((focusNodeRect.
left() >
contentsX()) && (focusNodeRect.
right() <
contentsX() +
visibleWidth()) &&
01537 (focusNodeRect.
top() >
contentsY()) && (focusNodeRect.
bottom() <
contentsY() +
visibleHeight())) {
01538
01539 visible =
true;
01540 }
01541
else {
01542
01543
if (
next)
01544 toFocus = doc->nextFocusNode(toFocus);
01545
else
01546 toFocus = doc->previousFocusNode(toFocus);
01547 }
01548 }
01549
01550
if (toFocus)
01551 newFocusNode = toFocus;
01552 }
01553
01554 d->scrollBarMoved =
false;
01555
01556
if (!newFocusNode)
01557 {
01558
01559
if (
next)
01560 scrollTo(
QRect(
contentsX()+
visibleWidth()/2,
contentsHeight(),0,0));
01561
else
01562 scrollTo(
QRect(
contentsX()+
visibleWidth()/2,0,0,0));
01563 }
01564
else
01565
01566 {
01567
#ifndef KHTML_NO_CARET
01568
01569
if (!m_part->
isCaretMode() && !m_part->
isEditable()
01570 && newFocusNode->contentEditable()) {
01571 d->caretViewContext();
01572 moveCaretTo(newFocusNode, 0L,
true);
01573 }
else {
01574 caretOff();
01575 }
01576
#endif // KHTML_NO_CARET
01577
01578
if (oldFocusNode)
01579 {
01580
if (!scrollTo(newFocusNode->getRect()))
01581
return;
01582 }
01583
else
01584 {
01585
ensureVisible(
contentsX(), next?0:
contentsHeight());
01586
01587 }
01588
01589 }
01590
01591
01592
Node guard(newFocusNode);
01593 m_part->
xmlDocImpl()->setFocusNode(newFocusNode);
01594
if( newFocusNode != NULL && newFocusNode->hasOneRef())
01595
return;
01596 emit m_part->
nodeActivated(
Node(newFocusNode));
01597 }
01598
01599
01600
bool KHTMLView::handleAccessKey(
const QKeyEvent* ev )
01601 {
01602
const int mods = Qt::AltButton | Qt::ControlButton;
01603
if( ( ev->
state() & mods ) != mods )
01604
return false;
01605
01606
01607
QChar c;
01608
if( ev->
key() >= Key_A && ev->
key() <= Key_Z )
01609 c =
'A' + ev->
key() - Key_A;
01610
else if( ev->
key() >= Key_0 && ev->
key() <= Key_9 )
01611 c =
'0' + ev->
key() - Key_0;
01612
else {
01613
01614
01615
if( ev->
text().length() == 1 )
01616 c = ev->
text()[ 0 ];
01617 }
01618
if( c.
isNull())
01619
return false;
01620
return focusNodeWithAccessKey( c );
01621 }
01622
01623
bool KHTMLView::focusNodeWithAccessKey(
QChar c,
KHTMLView* caller )
01624 {
01625 DocumentImpl *doc = m_part->
xmlDocImpl();
01626
if( !doc )
01627
return false;
01628 ElementImpl* node = doc->findAccessKeyElement( c );
01629
if( !node ) {
01630
QPtrList<KParts::ReadOnlyPart> frames = m_part->
frames();
01631
for(
QPtrListIterator<KParts::ReadOnlyPart> it( frames );
01632 it != NULL;
01633 ++it ) {
01634
if( !(*it)->inherits(
"KHTMLPart" ))
01635
continue;
01636
KHTMLPart*
part = static_cast< KHTMLPart* >( *it );
01637
if( part->
view() && part->
view() != caller
01638 && part->
view()->
focusNodeWithAccessKey( c,
this ))
01639
return true;
01640 }
01641
01642
if (m_part->
parentPart() && m_part->
parentPart()->
view()
01643 && m_part->
parentPart()->
view() != caller )
01644
return m_part->
parentPart()->
view()->
focusNodeWithAccessKey( c,
this );
01645
return false;
01646 }
01647
01648
01649
#ifndef KHTML_NO_CARET
01650
01651
if (!m_part->
isCaretMode() && !m_part->
isEditable()
01652 && node->contentEditable()) {
01653 d->caretViewContext();
01654 moveCaretTo(node, 0L,
true);
01655 }
else {
01656 caretOff();
01657 }
01658
#endif // KHTML_NO_CARET
01659
01660
QRect r = node->getRect();
01661
ensureVisible( r.
right(), r.
bottom());
01662
ensureVisible( r.
left(), r.
top());
01663
01664
Node guard( node );
01665
if( node->isSelectable()) {
01666
01667 m_part->
xmlDocImpl()->setFocusNode(node);
01668
if( node != NULL && node->hasOneRef())
01669
return true;
01670 emit m_part->
nodeActivated(
Node(node));
01671
if( node != NULL && node->hasOneRef())
01672
return true;
01673 }
01674
switch( node->id()) {
01675
case ID_A:
01676 static_cast< HTMLAnchorElementImpl* >( node )->click();
01677
break;
01678
case ID_INPUT:
01679 static_cast< HTMLInputElementImpl* >( node )->click();
01680
break;
01681
case ID_BUTTON:
01682 static_cast< HTMLButtonElementImpl* >( node )->click();
01683
break;
01684
case ID_AREA:
01685 static_cast< HTMLAreaElementImpl* >( node )->click();
01686
break;
01687
case ID_LABEL:
01688
01689
break;
01690
case ID_TEXTAREA:
01691
break;
01692
case ID_LEGEND:
01693
01694
break;
01695 }
01696
return true;
01697 }
01698
01699
void KHTMLView::setMediaType(
const QString &medium )
01700 {
01701 m_medium = medium;
01702 }
01703
01704
QString KHTMLView::mediaType()
const
01705
{
01706
return m_medium;
01707 }
01708
01709
void KHTMLView::setWidgetVisible(RenderWidget* w,
bool vis)
01710 {
01711
if (vis) {
01712 d->visibleWidgets.replace(w, w->widget());
01713 }
01714
else
01715 d->visibleWidgets.remove(w);
01716 }
01717
01718 void KHTMLView::print()
01719 {
01720
print(
false );
01721 }
01722
01723 void KHTMLView::print(
bool quick)
01724 {
01725
if(!m_part->
xmlDocImpl())
return;
01726 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->
xmlDocImpl()->renderer());
01727
if(!root)
return;
01728
01729
01730 KPrinter *printer =
new KPrinter(
true, QPrinter::PrinterResolution);
01731 printer->addDialogPage(
new KHTMLPrintSettings());
01732
QString docname = m_part->
xmlDocImpl()->URL().prettyURL();
01733
if ( !docname.
isEmpty() )
01734 docname =
KStringHandler::csqueeze(docname, 80);
01735
if(quick || printer->setup(
this, i18n(
"Print %1").arg(docname))) {
01736
viewport()->setCursor( waitCursor );
01737
01738 printer->setFullPage(
false);
01739 printer->setCreator(
QString(
"KDE %1.%2.%3 HTML Library").arg(KDE_VERSION_MAJOR).arg(KDE_VERSION_MINOR).arg(KDE_VERSION_RELEASE));
01740 printer->setDocName(docname);
01741
01742
QPainter *p =
new QPainter;
01743 p->
begin( printer );
01744 khtml::setPrintPainter( p );
01745
01746 m_part->
xmlDocImpl()->setPaintDevice( printer );
01747
QString oldMediaType = mediaType();
01748 setMediaType(
"print" );
01749
01750
01751
01752 m_part->
xmlDocImpl()->setPrintStyleSheet( printer->option(
"app-khtml-printfriendly") ==
"true" ?
01753
"* { background-image: none !important;"
01754
" background-color: white !important;"
01755
" color: black !important; }"
01756
"body { margin: 0px !important; }"
01757
"html { margin: 0px !important; }" :
01758
"body { margin: 0px !important; }"
01759
"html { margin: 0px !important; }"
01760 );
01761
01762
QPaintDeviceMetrics metrics( printer );
01763
01764
01765
01766
01767
01768
01769
kdDebug(6000) <<
"printing: physical page width = " << metrics.
width()
01770 <<
" height = " << metrics.
height() <<
endl;
01771 root->setPrintingMode(
true);
01772 root->setWidth(metrics.
width());
01773
01774 m_part->
xmlDocImpl()->styleSelector()->computeFontSizes(&metrics, 100);
01775 m_part->
xmlDocImpl()->updateStyleSelector();
01776 root->setPrintImages( printer->option(
"app-khtml-printimages") ==
"true");
01777 root->setMinMaxKnown(
false );
01778 root->setLayouted(
false );
01779 root->layout();
01780 khtml::RenderWidget::flushWidgetResizes();
01781
01782
bool printHeader = (printer->option(
"app-khtml-printheader") ==
"true");
01783
01784
int headerHeight = 0;
01785
QFont headerFont(
"helvetica", 8);
01786
01787
QString headerLeft =
KGlobal::locale()->
formatDate(QDate::currentDate(),
true);
01788
QString headerMid = docname;
01789
QString headerRight;
01790
01791
if (printHeader)
01792 {
01793 p->
setFont(headerFont);
01794 headerHeight = (p->
fontMetrics().lineSpacing() * 3) / 2;
01795 }
01796
01797
01798
kdDebug(6000) <<
"printing: html page width = " << root->docWidth()
01799 <<
" height = " << root->docHeight() <<
endl;
01800
kdDebug(6000) <<
"printing: margins left = " << printer->margins().width()
01801 <<
" top = " << printer->margins().height() <<
endl;
01802
kdDebug(6000) <<
"printing: paper width = " << metrics.
width()
01803 <<
" height = " << metrics.
height() <<
endl;
01804
01805
01806
int pageHeight = metrics.
height();
01807
int pageWidth = metrics.
width();
01808 p->
setClipRect(0,0, pageWidth, pageHeight);
01809
01810 pageHeight -= headerHeight;
01811
01812
bool scalePage =
false;
01813
double scale = 0.0;
01814
#ifndef QT_NO_TRANSFORMATIONS
01815
if(root->docWidth() > metrics.
width()) {
01816 scalePage =
true;
01817 scale = ((
double) metrics.
width())/((
double) root->docWidth());
01818 pageHeight = (
int) (pageHeight/scale);
01819 pageWidth = (
int) (pageWidth/scale);
01820 headerHeight = (
int) (headerHeight/scale);
01821 }
01822
#endif
01823
kdDebug(6000) <<
"printing: scaled html width = " << pageWidth
01824 <<
" height = " << pageHeight <<
endl;
01825
01826
01827
if (printHeader)
01828 {
01829
int available_width = metrics.
width() - 10 -
01830 2 * kMax(p->
boundingRect(0, 0, metrics.
width(), p->
fontMetrics().lineSpacing(), Qt::AlignLeft, headerLeft).width(),
01831 p->
boundingRect(0, 0, metrics.
width(), p->
fontMetrics().lineSpacing(), Qt::AlignLeft, headerRight).width());
01832
if (available_width < 150)
01833 available_width = 150;
01834
int mid_width;
01835
int squeeze = 120;
01836
do {
01837 headerMid =
KStringHandler::csqueeze(docname, squeeze);
01838 mid_width = p->
boundingRect(0, 0, metrics.
width(), p->
fontMetrics().lineSpacing(), Qt::AlignLeft, headerMid).width();
01839 squeeze -= 10;
01840 }
while (mid_width > available_width);
01841 }
01842
01843
int top = 0;
01844
int page = 1;
01845
while(top < root->docHeight()) {
01846
if(top > 0) printer->newPage();
01847
if (printHeader)
01848 {
01849
int dy = p->
fontMetrics().lineSpacing();
01850 p->
setPen(Qt::black);
01851 p->
setFont(headerFont);
01852
01853 headerRight =
QString(
"#%1").
arg(page);
01854
01855 p->
drawText(0, 0, metrics.
width(), dy, Qt::AlignLeft, headerLeft);
01856 p->
drawText(0, 0, metrics.
width(), dy, Qt::AlignHCenter, headerMid);
01857 p->
drawText(0, 0, metrics.
width(), dy, Qt::AlignRight, headerRight);
01858 }
01859
01860
#ifndef QT_NO_TRANSFORMATIONS
01861
if (scalePage)
01862 p->
scale(scale, scale);
01863
#endif
01864
p->
translate(0, headerHeight-top);
01865
01866 root->setTruncatedAt(top+pageHeight);
01867
01868 root->layer()->paint(p,
QRect(0, top, pageWidth, pageHeight));
01869
if (top + pageHeight >= root->docHeight())
01870
break;
01871
01872 top = root->truncatedAt();
01873 p->
resetXForm();
01874 page++;
01875 }
01876
01877 p->
end();
01878
delete p;
01879
01880
01881 root->setPrintingMode(
false);
01882 khtml::setPrintPainter( 0 );
01883 setMediaType( oldMediaType );
01884 m_part->
xmlDocImpl()->setPaintDevice(
this );
01885 m_part->
xmlDocImpl()->styleSelector()->computeFontSizes(m_part->
xmlDocImpl()->paintDeviceMetrics(), m_part->
zoomFactor());
01886 m_part->
xmlDocImpl()->updateStyleSelector();
01887
viewport()->unsetCursor();
01888 }
01889
delete printer;
01890 }
01891
01892
void KHTMLView::slotPaletteChanged()
01893 {
01894
if(!m_part->
xmlDocImpl())
return;
01895 DOM::DocumentImpl *document = m_part->
xmlDocImpl();
01896
if (!document->isHTMLDocument())
return;
01897 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(document->renderer());
01898
if(!root)
return;
01899 root->style()->resetPalette();
01900 NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
01901
if(!body)
return;
01902 body->setChanged(
true);
01903 body->recalcStyle( NodeImpl::Force );
01904 }
01905
01906
void KHTMLView::paint(
QPainter *p,
const QRect &rc,
int yOff,
bool *more)
01907 {
01908
if(!m_part->
xmlDocImpl())
return;
01909 khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->
xmlDocImpl()->renderer());
01910
if(!root)
return;
01911
01912 m_part->
xmlDocImpl()->setPaintDevice(p->
device());
01913 root->setPrintingMode(
true);
01914 root->setWidth(rc.
width());
01915
01916 p->
save();
01917 p->
setClipRect(rc);
01918 p->
translate(rc.
left(), rc.
top());
01919
double scale = ((
double) rc.
width()/(
double) root->docWidth());
01920
int height = (
int) ((
double) rc.
height() / scale);
01921
#ifndef QT_NO_TRANSFORMATIONS
01922
p->
scale(scale, scale);
01923
#endif
01924
01925 root->layer()->paint(p,
QRect(0, yOff, root->docWidth(), height));
01926
if (more)
01927 *more = yOff + height < root->docHeight();
01928 p->
restore();
01929
01930 root->setPrintingMode(
false);
01931 m_part->
xmlDocImpl()->setPaintDevice(
this );
01932 }
01933
01934
01935
void KHTMLView::useSlowRepaints()
01936 {
01937 d->useSlowRepaints =
true;
01938
setStaticBackground(
true);
01939 }
01940
01941
01942 void KHTMLView::setVScrollBarMode ( ScrollBarMode mode )
01943 {
01944
#ifndef KHTML_NO_SCROLLBARS
01945
d->vmode = mode;
01946
QScrollView::setVScrollBarMode(mode);
01947
#else
01948
Q_UNUSED( mode );
01949
#endif
01950
}
01951
01952 void KHTMLView::setHScrollBarMode ( ScrollBarMode mode )
01953 {
01954
#ifndef KHTML_NO_SCROLLBARS
01955
d->hmode = mode;
01956
QScrollView::setHScrollBarMode(mode);
01957
#else
01958
Q_UNUSED( mode );
01959
#endif
01960
}
01961
01962
void KHTMLView::restoreScrollBar()
01963 {
01964
int ow =
visibleWidth();
01965
QScrollView::setVScrollBarMode(d->vmode);
01966
if (
visibleWidth() != ow)
01967
layout();
01968 d->prevScrollbarVisible =
verticalScrollBar()->isVisible();
01969 }
01970
01971
QStringList KHTMLView::formCompletionItems(
const QString &name)
const
01972
{
01973
if (!m_part->
settings()->
isFormCompletionEnabled())
01974
return QStringList();
01975
if (!d->formCompletions)
01976 d->formCompletions =
new KSimpleConfig(
locateLocal(
"data",
"khtml/formcompletions"));
01977
return d->formCompletions->readListEntry(name);
01978 }
01979
01980
void KHTMLView::clearCompletionHistory(
const QString& name)
01981 {
01982
if (!d->formCompletions)
01983 {
01984 d->formCompletions =
new KSimpleConfig(
locateLocal(
"data",
"khtml/formcompletions"));
01985 }
01986 d->formCompletions->writeEntry(name,
"");
01987 d->formCompletions->sync();
01988 }
01989
01990
void KHTMLView::addFormCompletionItem(
const QString &name,
const QString &value)
01991 {
01992
if (!m_part->
settings()->
isFormCompletionEnabled())
01993
return;
01994
01995
01996
01997
bool cc_number(
true);
01998
for (
unsigned int i = 0; i < value.
length(); ++i)
01999 {
02000
QChar c(value[i]);
02001
if (!c.
isNumber() && c !=
'-' && !c.
isSpace())
02002 {
02003 cc_number =
false;
02004
break;
02005 }
02006 }
02007
if (cc_number)
02008
return;
02009
QStringList items = formCompletionItems(name);
02010
if (!items.contains(value))
02011 items.prepend(value);
02012
while ((
int)items.count() > m_part->
settings()->
maxFormCompletionItems())
02013 items.remove(items.fromLast());
02014 d->formCompletions->writeEntry(name, items);
02015 }
02016
02017
void KHTMLView::addNonPasswordStorableSite(
const QString& host)
02018 {
02019
if (!d->formCompletions) {
02020 d->formCompletions =
new KSimpleConfig(
locateLocal(
"data",
"khtml/formcompletions"));
02021 }
02022
02023 d->formCompletions->setGroup(
"NonPasswordStorableSites");
02024
QStringList sites = d->formCompletions->readListEntry(
"Sites");
02025 sites.append(host);
02026 d->formCompletions->writeEntry(
"Sites", sites);
02027 d->formCompletions->sync();
02028 d->formCompletions->setGroup(QString::null);
02029 }
02030
02031
bool KHTMLView::nonPasswordStorableSite(
const QString& host)
const
02032
{
02033
if (!d->formCompletions) {
02034 d->formCompletions =
new KSimpleConfig(
locateLocal(
"data",
"khtml/formcompletions"));
02035 }
02036 d->formCompletions->setGroup(
"NonPasswordStorableSites");
02037
QStringList sites = d->formCompletions->readListEntry(
"Sites");
02038 d->formCompletions->setGroup(QString::null);
02039
02040
return (sites.find(host) != sites.end());
02041 }
02042
02043
02044
bool KHTMLView::dispatchMouseEvent(
int eventId, DOM::NodeImpl *targetNode,
bool cancelable,
02045
int detail,
QMouseEvent *_mouse,
bool setUnder,
02046
int mouseEventType)
02047 {
02048
if (d->underMouse)
02049 d->underMouse->deref();
02050 d->underMouse = targetNode;
02051
if (d->underMouse)
02052 d->underMouse->ref();
02053
02054
int exceptioncode = 0;
02055
int pageX = 0;
02056
int pageY = 0;
02057
viewportToContents(_mouse->
x(), _mouse->
y(), pageX, pageY);
02058
int clientX = pageX -
contentsX();
02059
int clientY = pageY -
contentsY();
02060
int screenX = _mouse->
globalX();
02061
int screenY = _mouse->
globalY();
02062
int button = -1;
02063
switch (_mouse->
button()) {
02064
case LeftButton:
02065 button = 0;
02066
break;
02067
case MidButton:
02068 button = 1;
02069
break;
02070
case RightButton:
02071 button = 2;
02072
break;
02073
default:
02074
break;
02075 }
02076
bool ctrlKey = (_mouse->
state() & ControlButton);
02077
bool altKey = (_mouse->
state() & AltButton);
02078
bool shiftKey = (_mouse->
state() & ShiftButton);
02079
bool metaKey = (_mouse->
state() & MetaButton);
02080
02081
02082
if (setUnder && (d->prevMouseX != pageX || d->prevMouseY != pageY)) {
02083
02084
02085
02086 NodeImpl *oldUnder = 0;
02087
if (d->prevMouseX >= 0 && d->prevMouseY >= 0) {
02088 NodeImpl::MouseEvent mev( _mouse->
stateAfter(), static_cast<NodeImpl::MouseEventType>(mouseEventType));
02089 m_part->
xmlDocImpl()->prepareMouseEvent(
true, d->prevMouseX, d->prevMouseY, &mev );
02090 oldUnder = mev.innerNode.handle();
02091 }
02092
02093
if (oldUnder != targetNode) {
02094
02095
if (oldUnder){
02096 oldUnder->ref();
02097 MouseEventImpl *me =
new MouseEventImpl(EventImpl::MOUSEOUT_EVENT,
02098
true,
true,m_part->
xmlDocImpl()->defaultView(),
02099 0,screenX,screenY,clientX,clientY,pageX, pageY,
02100 ctrlKey,altKey,shiftKey,metaKey,
02101 button,targetNode);
02102 me->ref();
02103 oldUnder->dispatchEvent(me,exceptioncode,
true);
02104 me->deref();
02105 }
02106
02107
02108
if (targetNode) {
02109 MouseEventImpl *me =
new MouseEventImpl(EventImpl::MOUSEOVER_EVENT,
02110
true,
true,m_part->
xmlDocImpl()->defaultView(),
02111 0,screenX,screenY,clientX,clientY,pageX, pageY,
02112 ctrlKey,altKey,shiftKey,metaKey,
02113 button,oldUnder);
02114
02115 me->ref();
02116 targetNode->dispatchEvent(me,exceptioncode,
true);
02117 me->deref();
02118 }
02119
02120
if (oldUnder)
02121 oldUnder->deref();
02122 }
02123 }
02124
02125
bool swallowEvent =
false;
02126
02127
if (targetNode) {
02128
02129
bool dblclick = ( eventId == EventImpl::CLICK_EVENT &&
02130 _mouse->type() == QEvent::MouseButtonDblClick );
02131 MouseEventImpl *me =
new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
02132
true,cancelable,m_part->
xmlDocImpl()->defaultView(),
02133 detail,screenX,screenY,clientX,clientY,pageX, pageY,
02134 ctrlKey,altKey,shiftKey,metaKey,
02135 button,0, _mouse, dblclick );
02136 me->ref();
02137 targetNode->dispatchEvent(me,exceptioncode,
true);
02138
if (me->defaultHandled() || me->defaultPrevented())
02139 swallowEvent =
true;
02140 me->deref();
02141
02142
if (eventId == EventImpl::MOUSEDOWN_EVENT) {
02143
if (targetNode->isSelectable())
02144 m_part->
xmlDocImpl()->setFocusNode(targetNode);
02145
else
02146 m_part->
xmlDocImpl()->setFocusNode(0);
02147 }
02148 }
02149
02150
return swallowEvent;
02151 }
02152
02153
void KHTMLView::setIgnoreWheelEvents(
bool e )
02154 {
02155 d->ignoreWheelEvents = e;
02156 }
02157
02158
#ifndef QT_NO_WHEELEVENT
02159
02160
void KHTMLView::viewportWheelEvent(
QWheelEvent* e)
02161 {
02162
if ( ( e->
state() & ControlButton) == ControlButton )
02163 {
02164 emit zoomView( - e->
delta() );
02165 e->
accept();
02166 }
02167
else if ( ( (d->ignoreWheelEvents && !
verticalScrollBar()->isVisible())
02168 || e->
delta() > 0 &&
contentsY() <= 0
02169 || e->
delta() < 0 &&
contentsY() >=
contentsHeight() -
visibleHeight())
02170 && m_part->
parentPart() ) {
02171
kdDebug(6000) <<
this <<
" cz " <<
contentsY() <<
" ch " <<
contentsHeight() <<
" vh " <<
visibleHeight() <<
endl;
02172
if ( m_part->
parentPart()->
view() )
02173 m_part->
parentPart()->
view()->wheelEvent( e );
02174
kdDebug(6000) <<
"sent" <<
endl;
02175 e->
ignore();
02176 }
02177
else if ( d->vmode == QScrollView::AlwaysOff ) {
02178 e->
accept();
02179 }
02180
else {
02181 d->scrollBarMoved =
true;
02182 QScrollView::viewportWheelEvent( e );
02183
02184
QMouseEvent *tempEvent =
new QMouseEvent( QEvent::MouseMove,
QPoint(-1,-1),
QPoint(-1,-1), Qt::NoButton, e->
state() );
02185 emit viewportMouseMoveEvent ( tempEvent );
02186
delete tempEvent;
02187 }
02188
02189 }
02190
#endif
02191
02192
void KHTMLView::dragEnterEvent(
QDragEnterEvent* ev )
02193 {
02194
02195
02196
02197
if ( m_part->
parentPart() )
02198 {
02199
QApplication::sendEvent(m_part->
parentPart()->
widget(), ev);
02200
return;
02201 }
02202 QScrollView::dragEnterEvent( ev );
02203 }
02204
02205
void KHTMLView::dropEvent(
QDropEvent *ev )
02206 {
02207
02208
02209
02210
if ( m_part->
parentPart() )
02211 {
02212
QApplication::sendEvent(m_part->
parentPart()->
widget(), ev);
02213
return;
02214 }
02215 QScrollView::dropEvent( ev );
02216 }
02217
02218
void KHTMLView::focusInEvent(
QFocusEvent *e )
02219 {
02220
#ifndef KHTML_NO_CARET
02221
02222
02223
if (d->m_caretViewContext &&
02224 d->m_caretViewContext->freqTimerId == -1 &&
02225 m_part->
xmlDocImpl()) {
02226 NodeImpl *caretNode = m_part->
xmlDocImpl()->focusNode();
02227
if (m_part->
isCaretMode()
02228 || m_part->
isEditable()
02229 || (caretNode && caretNode->renderer()
02230 && caretNode->renderer()->style()->userInput()
02231 == UI_ENABLED)) {
02232 d->m_caretViewContext->freqTimerId = startTimer(500);
02233 d->m_caretViewContext->visible =
true;
02234 }
02235 }
02236 showCaret();
02237
#endif // KHTML_NO_CARET
02238
QScrollView::focusInEvent( e );
02239 }
02240
02241
void KHTMLView::focusOutEvent(
QFocusEvent *e )
02242 {
02243
if(m_part) m_part->
stopAutoScroll();
02244
02245
#ifndef KHTML_NO_CARET
02246
if (d->m_caretViewContext) {
02247
switch (d->m_caretViewContext->displayNonFocused) {
02248
case KHTMLPart::CaretInvisible:
02249 hideCaret();
02250
break;
02251
case KHTMLPart::CaretVisible: {
02252 killTimer(d->m_caretViewContext->freqTimerId);
02253 d->m_caretViewContext->freqTimerId = -1;
02254 NodeImpl *caretNode = m_part->
xmlDocImpl()->focusNode();
02255
if (!d->m_caretViewContext->visible && (m_part->
isCaretMode()
02256 || m_part->
isEditable()
02257 || (caretNode && caretNode->renderer()
02258 && caretNode->renderer()->style()->userInput()
02259 == UI_ENABLED))) {
02260 d->m_caretViewContext->visible =
true;
02261 showCaret(
true);
02262 }
02263
break;
02264 }
02265
case KHTMLPart::CaretBlink:
02266
02267
break;
02268 }
02269 }
02270
#endif // KHTML_NO_CARET
02271
QScrollView::focusOutEvent( e );
02272 }
02273
02274
void KHTMLView::slotScrollBarMoved()
02275 {
02276
if (!d->scrollingSelf)
02277 d->scrollBarMoved =
true;
02278 }
02279
02280
void KHTMLView::timerEvent (
QTimerEvent *e )
02281 {
02282
02283
if ( e->
timerId() == d->scrollTimerId ) {
02284
if( d->scrollSuspended )
02285
return;
02286
switch (d->scrollDirection) {
02287
case KHTMLViewPrivate::ScrollDown:
02288
if (
contentsY() +
visibleHeight () >=
contentsHeight())
02289 d->newScrollTimer(
this, 0);
02290
else
02291
scrollBy( 0, d->scrollBy );
02292
break;
02293
case KHTMLViewPrivate::ScrollUp:
02294
if (
contentsY() <= 0)
02295 d->newScrollTimer(
this, 0);
02296
else
02297
scrollBy( 0, -d->scrollBy );
02298
break;
02299
case KHTMLViewPrivate::ScrollRight:
02300
if (
contentsX() +
visibleWidth () >=
contentsWidth())
02301 d->newScrollTimer(
this, 0);
02302
else
02303
scrollBy( d->scrollBy, 0 );
02304
break;
02305
case KHTMLViewPrivate::ScrollLeft:
02306
if (
contentsX() <= 0)
02307 d->newScrollTimer(
this, 0);
02308
else
02309
scrollBy( -d->scrollBy, 0 );
02310
break;
02311 }
02312
return;
02313 }
02314
else if ( e->
timerId() == d->layoutTimerId ) {
02315 d->firstRelayout =
false;
02316 d->dirtyLayout =
true;
02317
layout();
02318 }
02319
#ifndef KHTML_NO_CARET
02320
else if (d->m_caretViewContext
02321 && e->
timerId() == d->m_caretViewContext->freqTimerId) {
02322 d->m_caretViewContext->visible = !d->m_caretViewContext->visible;
02323
if (d->m_caretViewContext->displayed) {
02324
updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
02325 d->m_caretViewContext->width,
02326 d->m_caretViewContext->height);
02327 }
02328
02329
02330
return;
02331 }
02332
#endif
02333
02334
if( m_part->
xmlDocImpl() ) {
02335 DOM::DocumentImpl *document = m_part->
xmlDocImpl();
02336 khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer());
02337
02338
if ( root && !root->layouted() ) {
02339 killTimer(d->repaintTimerId);
02340 d->repaintTimerId = 0;
02341 scheduleRelayout();
02342
return;
02343 }
02344 }
02345
02346
setStaticBackground(d->useSlowRepaints);
02347
02348
02349 killTimer(d->repaintTimerId);
02350 d->repaintTimerId = 0;
02351
02352
QRegion updateRegion;
02353
QMemArray<QRect> rects = d->updateRegion.rects();
02354
02355 d->updateRegion =
QRegion();
02356
02357
if ( rects.
size() )
02358 updateRegion = rects[0];
02359
02360
for (
unsigned i = 1; i < rects.size(); ++i ) {
02361
QRect obR = updateRegion.
boundingRect();
02362
QRegion newRegion = updateRegion.
unite(rects[i]);
02363
if (2*newRegion.
boundingRect().height() > 3*obR.
height() )
02364 {
02365
repaintContents( obR );
02366 updateRegion = rects[i];
02367 }
02368
else
02369 updateRegion = newRegion;
02370 }
02371
02372
if ( !updateRegion.
isNull() )
02373
repaintContents( updateRegion.
boundingRect() );
02374
02375
if (d->dirtyLayout && !d->visibleWidgets.isEmpty()) {
02376
QWidget* w;
02377 d->dirtyLayout =
false;
02378
02379
QRect visibleRect(
contentsX(),
contentsY(),
visibleWidth(),
visibleHeight());
02380
QPtrList<RenderWidget> toRemove;
02381
for (
QPtrDictIterator<QWidget> it(d->visibleWidgets); it.current(); ++it) {
02382
int xp = 0, yp = 0;
02383 w = it.current();
02384 RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
02385
if (!rw->absolutePosition(xp, yp) ||
02386 !visibleRect.intersects(
QRect(xp, yp, w->
width(), w->
height())))
02387 toRemove.
append(rw);
02388 }
02389
for (RenderWidget* r = toRemove.
first(); r; r = toRemove.
next())
02390
if ( (w = d->visibleWidgets.take(r) ) )
02391
addChild(w, 0, -500000);
02392 }
02393 }
02394
02395
void KHTMLView::scheduleRelayout(khtml::RenderObject * )
02396 {
02397
if (!d->layoutSchedulingEnabled || d->layoutTimerId)
02398
return;
02399
02400 d->layoutTimerId = startTimer( m_part->
xmlDocImpl() && m_part->
xmlDocImpl()->parsing()
02401 ? 1000 : 0 );
02402 }
02403
02404
void KHTMLView::unscheduleRelayout()
02405 {
02406
if (!d->layoutTimerId)
02407
return;
02408
02409 killTimer(d->layoutTimerId);
02410 d->layoutTimerId = 0;
02411 }
02412
02413
void KHTMLView::unscheduleRepaint()
02414 {
02415
if (!d->repaintTimerId)
02416
return;
02417
02418 killTimer(d->repaintTimerId);
02419 d->repaintTimerId = 0;
02420 }
02421
02422
void KHTMLView::scheduleRepaint(
int x,
int y,
int w,
int h)
02423 {
02424
bool parsing = !m_part->
xmlDocImpl() || m_part->
xmlDocImpl()->parsing();
02425
02426
02427
02428
02429
int time = parsing ? 300 : ( !d->complete ? 100 : 20 );
02430
02431
#ifdef DEBUG_FLICKER
02432
QPainter p;
02433 p.
begin(
viewport() );
02434
02435
int vx, vy;
02436
contentsToViewport( x, y, vx, vy );
02437 p.
fillRect( vx, vy, w, h, Qt::red );
02438 p.
end();
02439
#endif
02440
02441 d->updateRegion = d->updateRegion.unite(
QRect(x,y,w,h));
02442
02443
if ( !d->repaintTimerId )
02444 d->repaintTimerId = startTimer( time );
02445
02446
02447 }
02448
02449
void KHTMLView::complete()
02450 {
02451
02452
02453 d->complete =
true;
02454
02455
02456
if (d->layoutTimerId)
02457 {
02458
02459
02460 killTimer(d->layoutTimerId);
02461 d->layoutTimerId = startTimer( 0 );
02462 }
02463
02464
02465
if (d->repaintTimerId)
02466 {
02467
02468
02469 killTimer(d->repaintTimerId);
02470 d->repaintTimerId = startTimer( 20 );
02471 }
02472 }
02473
02474
#ifndef KHTML_NO_CARET
02475
02476
02477
02478
02479
#include "khtml_caret.cpp"
02480
02481
void KHTMLView::initCaret(
bool keepSelection)
02482 {
02483
#if DEBUG_CARETMODE > 0
02484
kdDebug(6200) <<
"begin initCaret" <<
endl;
02485
#endif
02486
02487
if (m_part->
xmlDocImpl()) {
02488 d->caretViewContext();
02489
bool cmoved = d->m_caretViewContext->caretMoved;
02490
if (m_part->
d->caretNode().isNull()) {
02491
02492 m_part->
d->caretNode() = m_part->
document();
02493 m_part->
d->caretOffset() = 0L;
02494
02495
02496
02497
if (!m_part->
d->caretNode().handle()->renderer())
return;
02498 }
02499
02500
02501
02502 moveCaretTo(m_part->
d->caretNode().handle(), m_part->
d->caretOffset(), !keepSelection);
02503
02504
02505 d->m_caretViewContext->caretMoved = cmoved;
02506 }
02507
#if DEBUG_CARETMODE > 0
02508
kdDebug(6200) <<
"end initCaret" <<
endl;
02509
#endif
02510
}
02511
02512
bool KHTMLView::caretOverrides()
const
02513
{
02514
bool cm = m_part->
isCaretMode();
02515
bool dm = m_part->
isEditable();
02516
return cm && !dm ?
false
02517 : (dm || m_part->
d->caretNode().handle()->contentEditable())
02518 && d->editorContext()->override;
02519 }
02520
02521
void KHTMLView::ensureNodeHasFocus(NodeImpl *node)
02522 {
02523
if (m_part->
isCaretMode() || m_part->
isEditable())
return;
02524
if (node->focused())
return;
02525
02526
02527 NodeImpl *firstAncestor = 0;
02528
while (node) {
02529
if (node->renderer()
02530 && node->renderer()->style()->userInput() != UI_ENABLED)
02531
break;
02532 firstAncestor = node;
02533 node = node->parentNode();
02534 }
02535
02536
if (!node) firstAncestor = 0;
02537
02538 DocumentImpl *doc = m_part->
xmlDocImpl();
02539
02540
if (!firstAncestor && doc->focusNode() && doc->focusNode()->renderer()
02541 && doc->focusNode()->renderer()->isWidget())
02542
return;
02543
02544
02545
#if DEBUG_CARETMODE > 1
02546
kdDebug(6200) <<
k_funcinfo <<
"firstAncestor " << firstAncestor <<
": "
02547 << (firstAncestor ? firstAncestor->nodeName().string() :
QString::null) <<
endl;
02548
#endif
02549
doc->setFocusNode(firstAncestor);
02550 emit m_part->
nodeActivated(
Node(firstAncestor));
02551 }
02552
02553
void KHTMLView::recalcAndStoreCaretPos(InlineBox *hintBox)
02554 {
02555
if (!m_part || m_part->
d->caretNode().isNull())
return;
02556 d->caretViewContext();
02557 NodeImpl *caretNode = m_part->
d->caretNode().handle();
02558
#if DEBUG_CARETMODE > 0
02559
kdDebug(6200) <<
"recalcAndStoreCaretPos: caretNode=" << caretNode << (caretNode ?
" "+caretNode->nodeName().string() :
QString::null) <<
" r@" << caretNode->renderer() << (caretNode->renderer() && caretNode->renderer()->isText() ?
" \"" +
QConstString(static_cast<RenderText *>(caretNode->renderer())->str->s, kMin(static_cast<RenderText *>(caretNode->renderer())->str->l, 15u)).string() +
"\"" :
QString::null) <<
endl;
02560
#endif
02561
caretNode->getCaret(m_part->
d->caretOffset(),
02562 caretOverrides(),
02563 d->m_caretViewContext->x, d->m_caretViewContext->y,
02564 d->m_caretViewContext->width,
02565 d->m_caretViewContext->height);
02566
02567
if (hintBox && d->m_caretViewContext->x == -1) {
02568
#if DEBUG_CARETMODE > 1
02569
kdDebug(6200) <<
"using hint inline box coordinates" <<
endl;
02570
#endif
02571
RenderObject *r = caretNode->renderer();
02572
const QFontMetrics &fm = r->style()->fontMetrics();
02573
int absx, absy;
02574 r->containingBlock()->absolutePosition(absx, absy,
02575
false);
02576 d->m_caretViewContext->x = absx + hintBox->xPos();
02577 d->m_caretViewContext->y = absy + hintBox->yPos()
02578 + hintBox->baseline() - fm.
ascent();
02579 d->m_caretViewContext->width = 1;
02580
02581
02582 d->m_caretViewContext->height = fm.
height();
02583 }
02584
02585
#if DEBUG_CARETMODE > 4
02586
02587
#endif
02588
#if DEBUG_CARETMODE > 0
02589
kdDebug(6200) <<
"caret: ofs="<<m_part->
d->caretOffset()<<
" "
02590 <<
" x="<<d->m_caretViewContext->x<<
" y="<<d->m_caretViewContext->y
02591 <<
" h="<<d->m_caretViewContext->height<<
endl;
02592
#endif
02593
}
02594
02595
void KHTMLView::caretOn()
02596 {
02597
if (d->m_caretViewContext) {
02598 killTimer(d->m_caretViewContext->freqTimerId);
02599
02600
if (hasFocus() || d->m_caretViewContext->displayNonFocused
02601 == KHTMLPart::CaretBlink) {
02602 d->m_caretViewContext->freqTimerId = startTimer(500);
02603 }
else {
02604 d->m_caretViewContext->freqTimerId = -1;
02605 }
02606
02607 d->m_caretViewContext->visible =
true;
02608
if ((d->m_caretViewContext->displayed = (hasFocus()
02609 || d->m_caretViewContext->displayNonFocused
02610 != KHTMLPart::CaretInvisible))) {
02611
updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
02612 d->m_caretViewContext->width,
02613 d->m_caretViewContext->height);
02614 }
02615
02616 }
02617 }
02618
02619
void KHTMLView::caretOff()
02620 {
02621
if (d->m_caretViewContext) {
02622 killTimer(d->m_caretViewContext->freqTimerId);
02623 d->m_caretViewContext->freqTimerId = -1;
02624 d->m_caretViewContext->displayed =
false;
02625
if (d->m_caretViewContext->visible) {
02626 d->m_caretViewContext->visible =
false;
02627
updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
02628 d->m_caretViewContext->width,
02629 d->m_caretViewContext->height);
02630 }
02631
02632 }
02633 }
02634
02635
void KHTMLView::showCaret(
bool forceRepaint)
02636 {
02637
if (d->m_caretViewContext) {
02638 d->m_caretViewContext->displayed =
true;
02639
if (d->m_caretViewContext->visible) {
02640
if (!forceRepaint) {
02641
updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
02642 d->m_caretViewContext->width,
02643 d->m_caretViewContext->height);
02644 }
else {
02645
repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
02646 d->m_caretViewContext->width,
02647 d->m_caretViewContext->height);
02648 }
02649 }
02650
02651 }
02652 }
02653
02654
bool KHTMLView::foldSelectionToCaret(NodeImpl *startNode,
long startOffset,
02655 NodeImpl *endNode,
long endOffset)
02656 {
02657 m_part->
d->m_selectionStart = m_part->
d->m_selectionEnd = m_part->
d->caretNode();
02658 m_part->
d->m_startOffset = m_part->
d->m_endOffset = m_part->
d->caretOffset();
02659 m_part->
d->m_extendAtEnd =
true;
02660
02661
bool folded = startNode != endNode || startOffset != endOffset;
02662
02663
02664
if (folded) {
02665 m_part->
xmlDocImpl()->clearSelection();
02666 }
02667
02668
return folded;
02669 }
02670
02671
void KHTMLView::hideCaret()
02672 {
02673
if (d->m_caretViewContext) {
02674
if (d->m_caretViewContext->visible) {
02675
02676 d->m_caretViewContext->visible =
false;
02677
02678
02679
repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
02680 d->m_caretViewContext->width,
02681 d->m_caretViewContext->height);
02682 d->m_caretViewContext->visible =
true;
02683 }
02684 d->m_caretViewContext->displayed =
false;
02685
02686 }
02687 }
02688
02689
int KHTMLView::caretDisplayPolicyNonFocused()
const
02690
{
02691
if (d->m_caretViewContext)
02692
return d->m_caretViewContext->displayNonFocused;
02693
else
02694
return KHTMLPart::CaretInvisible;
02695 }
02696
02697
void KHTMLView::setCaretDisplayPolicyNonFocused(
int policy)
02698 {
02699 d->caretViewContext();
02700
02701 d->m_caretViewContext->displayNonFocused = (
KHTMLPart::CaretDisplayPolicy)policy;
02702
02703
02704
if (!hasFocus()) {
02705
switch (d->m_caretViewContext->displayNonFocused) {
02706
case KHTMLPart::CaretInvisible:
02707 hideCaret();
02708
break;
02709
case KHTMLPart::CaretBlink:
02710
if (d->m_caretViewContext->freqTimerId != -1)
break;
02711 d->m_caretViewContext->freqTimerId = startTimer(500);
02712
02713
case KHTMLPart::CaretVisible:
02714 d->m_caretViewContext->displayed =
true;
02715 showCaret();
02716
break;
02717 }
02718 }
02719 }
02720
02721
bool KHTMLView::placeCaret(InlineBox *hintBox)
02722 {
02723
CaretViewContext *cv = d->caretViewContext();
02724 caretOff();
02725 NodeImpl *caretNode = m_part->
d->caretNode().handle();
02726
02727
if (!caretNode || !caretNode->renderer())
return false;
02728 ensureNodeHasFocus(caretNode);
02729
if (m_part->
isCaretMode() || m_part->
isEditable()
02730 || caretNode->renderer()->style()->userInput() == UI_ENABLED) {
02731 recalcAndStoreCaretPos(hintBox);
02732
02733 cv->
origX = cv->
x;
02734
02735 caretOn();
02736
return true;
02737 }
02738
return false;
02739 }
02740
02741
void KHTMLView::ensureCaretVisible()
02742 {
02743
CaretViewContext *cv = d->m_caretViewContext;
02744
if (!cv)
return;
02745
ensureVisible(cv->
x, cv->
y, cv->
width, cv->
height);
02746 d->scrollBarMoved =
false;
02747 }
02748
02749
bool KHTMLView::extendSelection(NodeImpl *oldStartSel,
long oldStartOfs,
02750 NodeImpl *oldEndSel,
long oldEndOfs)
02751 {
02752
bool changed =
false;
02753
if (m_part->
d->m_selectionStart == m_part->
d->m_selectionEnd
02754 && m_part->
d->m_startOffset == m_part->
d->m_endOffset) {
02755 changed = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
02756 m_part->
d->m_extendAtEnd =
true;
02757 }
else do {
02758 changed = m_part->
d->m_selectionStart.handle() != oldStartSel
02759 || m_part->
d->m_startOffset != oldStartOfs
02760 || m_part->
d->m_selectionEnd.handle() != oldEndSel
02761 || m_part->
d->m_endOffset != oldEndOfs;
02762
if (!changed)
break;
02763
02764
02765 NodeImpl *startNode;
02766
long startOffset;
02767
if (m_part->
d->m_extendAtEnd) {
02768 startNode = m_part->
d->m_selectionStart.handle();
02769 startOffset = m_part->
d->m_startOffset;
02770 }
else {
02771 startNode = m_part->
d->m_selectionEnd.handle();
02772 startOffset = m_part->
d->m_endOffset;
02773 m_part->
d->m_selectionEnd = m_part->
d->m_selectionStart;
02774 m_part->
d->m_endOffset = m_part->
d->m_startOffset;
02775 }
02776
02777
bool swapNeeded =
false;
02778
if (!m_part->
d->m_selectionEnd.isNull() && startNode) {
02779 swapNeeded = RangeImpl::compareBoundaryPoints(startNode, startOffset,
02780 m_part->
d->m_selectionEnd.handle(),
02781 m_part->
d->m_endOffset) >= 0;
02782 }
02783
02784 m_part->
d->m_selectionStart = startNode;
02785 m_part->
d->m_startOffset = startOffset;
02786
02787
if (swapNeeded) {
02788 m_part->
xmlDocImpl()->setSelection(m_part->
d->m_selectionEnd.handle(),
02789 m_part->
d->m_endOffset, m_part->
d->m_selectionStart.handle(),
02790 m_part->
d->m_startOffset);
02791 }
else {
02792 m_part->
xmlDocImpl()->setSelection(m_part->
d->m_selectionStart.handle(),
02793 m_part->
d->m_startOffset, m_part->
d->m_selectionEnd.handle(),
02794 m_part->
d->m_endOffset);
02795 }
02796 }
while(
false);
02797
return changed;
02798 }
02799
02800
void KHTMLView::updateSelection(NodeImpl *oldStartSel,
long oldStartOfs,
02801 NodeImpl *oldEndSel,
long oldEndOfs)
02802 {
02803
if (m_part->
d->m_selectionStart == m_part->
d->m_selectionEnd
02804 && m_part->
d->m_startOffset == m_part->
d->m_endOffset) {
02805
if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs)) {
02806 m_part->
emitSelectionChanged();
02807 }
02808 m_part->
d->m_extendAtEnd =
true;
02809 }
else {
02810
02811
if (!m_part->
d->m_selectionEnd.isNull() && !m_part->
d->m_selectionEnd.isNull()) {
02812
bool swapNeeded = RangeImpl::compareBoundaryPoints(
02813 m_part->
d->m_selectionStart.handle(), m_part->
d->m_startOffset,
02814 m_part->
d->m_selectionEnd.handle(), m_part->
d->m_endOffset) >= 0;
02815
if (swapNeeded) {
02816
DOM::Node tmpNode = m_part->
d->m_selectionStart;
02817
long tmpOffset = m_part->
d->m_startOffset;
02818 m_part->
d->m_selectionStart = m_part->
d->m_selectionEnd;
02819 m_part->
d->m_startOffset = m_part->
d->m_endOffset;
02820 m_part->
d->m_selectionEnd = tmpNode;
02821 m_part->
d->m_endOffset = tmpOffset;
02822 m_part->
d->m_startBeforeEnd =
true;
02823 m_part->
d->m_extendAtEnd = !m_part->
d->m_extendAtEnd;
02824 }
02825 }
02826
02827 m_part->
xmlDocImpl()->setSelection(m_part->
d->m_selectionStart.handle(),
02828 m_part->
d->m_startOffset, m_part->
d->m_selectionEnd.handle(),
02829 m_part->
d->m_endOffset);
02830 m_part->
emitSelectionChanged();
02831 }
02832 }
02833
02834
void KHTMLView::caretKeyPressEvent(
QKeyEvent *_ke)
02835 {
02836 NodeImpl *oldStartSel = m_part->
d->m_selectionStart.handle();
02837
long oldStartOfs = m_part->
d->m_startOffset;
02838 NodeImpl *oldEndSel = m_part->
d->m_selectionEnd.handle();
02839
long oldEndOfs = m_part->
d->m_endOffset;
02840
02841 NodeImpl *oldCaretNode = m_part->
d->caretNode().handle();
02842
long oldOffset = m_part->
d->caretOffset();
02843
02844
bool ctrl = _ke->
state() & ControlButton;
02845
02846
02847
switch(_ke->
key()) {
02848
case Key_Space:
02849
break;
02850
02851
case Key_Down:
02852 moveCaretNextLine(1);
02853
break;
02854
02855
case Key_Up:
02856 moveCaretPrevLine(1);
02857
break;
02858
02859
case Key_Left:
02860 moveCaretBy(
false, ctrl ? CaretByWord : CaretByCharacter, 1);
02861
break;
02862
02863
case Key_Right:
02864 moveCaretBy(
true, ctrl ? CaretByWord : CaretByCharacter, 1);
02865
break;
02866
02867
case Key_Next:
02868 moveCaretNextPage();
02869
break;
02870
02871
case Key_Prior:
02872 moveCaretPrevPage();
02873
break;
02874
02875
case Key_Home:
02876
if (ctrl)
02877 moveCaretToDocumentBoundary(
false);
02878
else
02879 moveCaretToLineBegin();
02880
break;
02881
02882
case Key_End:
02883
if (ctrl)
02884 moveCaretToDocumentBoundary(
true);
02885
else
02886 moveCaretToLineEnd();
02887
break;
02888
02889 }
02890
02891
if ((m_part->
d->caretNode().handle() != oldCaretNode
02892 || m_part->
d->caretOffset() != oldOffset)
02893
02894 && !m_part->
d->caretNode().isNull()) {
02895
02896 d->m_caretViewContext->caretMoved =
true;
02897
02898
if (_ke->
state() & ShiftButton) {
02899 updateSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
02900 }
else {
02901
if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs))
02902 m_part->
emitSelectionChanged();
02903 }
02904
02905 m_part->
emitCaretPositionChanged(m_part->
d->caretNode(), m_part->
d->caretOffset());
02906 }
02907
02908 _ke->
accept();
02909 }
02910
02911
bool KHTMLView::moveCaretTo(NodeImpl *node,
long offset,
bool clearSel)
02912 {
02913 sanitizeCaretState(node, offset);
02914
if (!node)
return false;
02915
02916
02917
02918
02919 RenderArena arena;
02920 RenderFlow *cb;
02921 InlineBox *box = 0;
02922 findFlowBox(node, offset, &arena, cb, &box);
02923
if (box && box->object() != node->renderer()) {
02924
if (box->object()->element()) {
02925 node = box->object()->element();
02926 offset = node->minOffset();
02927
#if DEBUG_CARETMODE > 1
02928
kdDebug(6200) <<
"set new node " << node->nodeName().string() <<
"@" << node <<
endl;
02929
#endif
02930
}
else {
02931
02932 box = 0;
02933
kdError(6200) <<
"Box contains no node! Crash imminent" <<
endl;
02934 }
02935 }
02936
02937 NodeImpl *oldStartSel = m_part->
d->m_selectionStart.handle();
02938
long oldStartOfs = m_part->
d->m_startOffset;
02939 NodeImpl *oldEndSel = m_part->
d->m_selectionEnd.handle();
02940
long oldEndOfs = m_part->
d->m_endOffset;
02941
02942
02943
bool posChanged = m_part->
d->caretNode().handle() != node
02944 || m_part->
d->caretOffset() != offset;
02945
bool selChanged =
false;
02946
02947 m_part->
d->caretNode() = node;
02948 m_part->
d->caretOffset() = offset;
02949
if (clearSel || !oldStartSel || !oldEndSel) {
02950 selChanged = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
02951 }
else {
02952
02953
02954 selChanged = extendSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
02955
02956
02957 }
02958
02959 d->caretViewContext()->caretMoved =
true;
02960
02961
bool visible_caret = placeCaret(box);
02962
02963
02964
02965
02966
if (posChanged) {
02967 m_part->
emitCaretPositionChanged(visible_caret ? node : 0, offset);
02968 }
02969
02970
return selChanged;
02971 }
02972
02973
void KHTMLView::moveCaretByLine(
bool next,
int count)
02974 {
02975
02976
02977
Node &caretNodeRef = m_part->
d->caretNode();
02978
if (caretNodeRef.
isNull())
return;
02979
02980 NodeImpl *caretNode = caretNodeRef.
handle();
02981
02982
long offset = m_part->
d->caretOffset();
02983
02984
CaretViewContext *cv = d->caretViewContext();
02985
02986 LinearDocument ld(m_part, caretNode, offset);
02987
02988 ErgonomicEditableLineIterator it(ld.current(), cv->
origX);
02989
02990
02991
while (count > 0 && it != ld.end() && it != ld.preBegin()) {
02992 count--;
02993
if (
next) ++it;
else --it;
02994 }
02995
02996
02997
if (it == ld.end() || it == ld.preBegin())
return;
02998
02999
int x, absx, absy;
03000 InlineBox *caretBox = nearestInlineBox(it, d->m_caretViewContext, x, absx, absy);
03001
03002 placeCaretOnLine(caretBox, x, absx, absy);
03003 }
03004
03005
void KHTMLView::placeCaretOnLine(InlineBox *caretBox,
int x,
int absx,
int absy)
03006 {
03007
03008
if (!caretBox)
return;
03009
03010 RenderObject *caretRender = caretBox->object();
03011 NodeImpl *caretNode = caretRender->element();
03012
03013
#if DEBUG_CARETMODE > 0
03014
kdDebug(6200) <<
"got valid caretBox " << caretBox <<
endl;
03015
kdDebug(6200) <<
"xPos: " << caretBox->xPos() <<
" yPos: " << caretBox->yPos()
03016 <<
" width: " << caretBox->width() <<
" height: " << caretBox->height() <<
endl;
03017
if (caretBox->isInlineTextBox()) {
kdDebug(6200) <<
"contains \"" <<
QString(((RenderText *)((InlineTextBox *)caretBox)->object())->str->s + ((InlineTextBox *)caretBox)->m_start, ((InlineTextBox *)caretBox)->m_len) <<
"\"" <<
endl;}
03018
#endif
03019
03020
int caretHeight = caretBox->height();
03021
bool isText = caretBox->isInlineTextBox();
03022
int yOfs = 0;
03023
if (isText) {
03024
03025 RenderText *t = static_cast<RenderText *>(caretRender);
03026
const QFontMetrics &fm = t->metrics(caretBox->m_firstLine);
03027 caretHeight = fm.
height();
03028 yOfs = caretBox->baseline() - fm.
ascent();
03029 }
03030
03031 caretOff();
03032
03033
03034 m_part->
d->caretNode() = caretNode;
03035
long &offset = m_part->
d->caretOffset();
03036
03037
03038 d->m_caretViewContext->y = caretBox->yPos() + yOfs;
03039 d->m_caretViewContext->height = caretHeight;
03040 d->m_caretViewContext->width = 1;
03041
03042
int xPos = caretBox->xPos();
03043
int caretBoxWidth = caretBox->width();
03044
03045
03046
if (x <= xPos) {
03047 d->m_caretViewContext->x = xPos;
03048 offset = caretBox->minOffset();
03049
03050 }
else if (x > xPos && x <= xPos + caretBoxWidth) {
03051
if (isText) {
03052 offset = static_cast<InlineTextBox *>(caretBox)->offsetForPoint(x,
03053 d->m_caretViewContext->x);
03054
#if DEBUG_CARETMODE > 2
03055
kdDebug(6200) <<
"deviation from origX " << d->m_caretViewContext->x - x <<
endl;
03056
#endif
03057
}
else {
03058
if (xPos + caretBoxWidth - x < x - xPos) {
03059 d->m_caretViewContext->x = xPos + caretBoxWidth;
03060 offset = caretNode ? caretNode->maxOffset() : 1;
03061 }
else {
03062 d->m_caretViewContext->x = xPos;
03063 offset = caretNode ? caretNode->minOffset() : 0;
03064 }
03065 }
03066 }
else {
03067 d->m_caretViewContext->x = xPos + caretBoxWidth;
03068 offset = caretBox->maxOffset();
03069 }
03070
#if DEBUG_CARETMODE > 0
03071
kdDebug(6200) <<
"new offset: " << offset <<
endl;
03072
#endif
03073
03074 d->m_caretViewContext->x += absx;
03075 d->m_caretViewContext->y += absy;
03076
03077
ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y,
03078 d->m_caretViewContext->width, d->m_caretViewContext->height);
03079 d->scrollBarMoved =
false;
03080
03081 ensureNodeHasFocus(caretNode);
03082 caretOn();
03083 }
03084
03085
void KHTMLView::moveCaretToLineBoundary(
bool end)
03086 {
03087
03088
03089
Node &caretNodeRef = m_part->
d->caretNode();
03090
if (caretNodeRef.
isNull())
return;
03091
03092 NodeImpl *caretNode = caretNodeRef.
handle();
03093
03094
long offset = m_part->
d->caretOffset();
03095
03096 LinearDocument ld(m_part, caretNode, offset);
03097
03098 EditableLineIterator it = ld.current();
03099
if (it == ld.end())
return;
03100
03101
EditableInlineBoxIterator fbit(it, end);
03102 InlineBox *b = *fbit;
03103 Q_ASSERT(b);
03104
03105 RenderObject *cb = (*it)->object();
03106
int absx, absy;
03107
03108
if (cb) cb->absolutePosition(absx,absy);
03109
else absx = absy = 0;
03110
03111
int x = b->xPos() + (
end ? b->width() : 0);
03112 d->m_caretViewContext->origX = absx + x;
03113 placeCaretOnLine(b, x, absx, absy);
03114 }
03115
03116
void KHTMLView::moveCaretToDocumentBoundary(
bool end)
03117 {
03118
03119
03120
Node &caretNodeRef = m_part->
d->caretNode();
03121
if (caretNodeRef.
isNull())
return;
03122
03123 NodeImpl *caretNode = caretNodeRef.
handle();
03124
03125
long offset = m_part->
d->caretOffset();
03126
03127 LinearDocument ld(m_part, caretNode, offset);
03128
03129 EditableLineIterator it(end ? ld.preEnd() : ld.begin(),
end);
03130
if (it == ld.end() || it == ld.preBegin())
return;
03131
03132
EditableInlineBoxIterator fbit = it;
03133 InlineBox *b = *fbit;
03134 Q_ASSERT(b);
03135
03136 RenderObject *cb = (*it)->object();
03137
int absx, absy;
03138
03139
if (cb) cb->absolutePosition(absx, absy);
03140
else absx = absy = 0;
03141
03142
int x = b->xPos();
03143 d->m_caretViewContext->origX = absx + x;
03144 placeCaretOnLine(b, x, absx, absy);
03145 }
03146
03147
void KHTMLView::moveCaretBy(
bool next, CaretMovement cmv,
int count)
03148 {
03149
if (!m_part)
return;
03150
03151
03152
Node &caretNodeRef = m_part->
d->caretNode();
03153
if (caretNodeRef.
isNull())
return;
03154
03155 NodeImpl *caretNode = caretNodeRef.
handle();
03156
03157
long &offset = m_part->
d->caretOffset();
03158
03159 LinearDocument ld(m_part, caretNode, offset);
03160
03161 EditableCharacterIterator it(&ld);
03162 InlineBox *hintBox = it.box();
03163
while (it.node() && count > 0) {
03164 count--;
03165
if (cmv == CaretByCharacter) {
03166
if (
next) ++it;
03167
else --it;
03168 }
else if (cmv == CaretByWord) {
03169
if (
next) moveItToNextWord(it);
03170
else moveItToPrevWord(it);
03171 }
03172 }
03173
if (it.node()) {
03174 caretNodeRef = it.node();
03175 offset = it.offset();
03176 hintBox = it.box();
03177
#if DEBUG_CARETMODE > 2
03178
kdDebug(6200) <<
"set by valid node. offset: " << offset <<
endl;
03179
#endif
03180
}
else {
03181 offset =
next ? caretNode->maxOffset() : caretNode->minOffset();
03182
#if DEBUG_CARETMODE > 0
03183
kdDebug(6200) <<
"set by INvalid node. offset: " << offset <<
endl;
03184
#endif
03185
}
03186 placeCaretOnChar(hintBox);
03187 }
03188
03189
void KHTMLView::placeCaretOnChar(InlineBox *hintBox)
03190 {
03191 caretOff();
03192 recalcAndStoreCaretPos(hintBox);
03193
ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y,
03194 d->m_caretViewContext->width, d->m_caretViewContext->height);
03195 d->m_caretViewContext->origX = d->m_caretViewContext->x;
03196 d->scrollBarMoved =
false;
03197
#if DEBUG_CARETMODE > 3
03198
03199
#endif
03200
ensureNodeHasFocus(m_part->
d->caretNode().handle());
03201 caretOn();
03202 }
03203
03204
void KHTMLView::moveCaretByPage(
bool next)
03205 {
03206
03207
03208
Node &caretNodeRef = m_part->
d->caretNode();
03209
if (caretNodeRef.
isNull())
return;
03210
03211 NodeImpl *caretNode = caretNodeRef.
handle();
03212
03213
long offset = m_part->
d->caretOffset();
03214
03215
int offs = (
clipper()->height() < 30) ?
clipper()->height() : 30;
03216
03217
int mindist =
clipper()->height() - offs;
03218
03219
CaretViewContext *cv = d->caretViewContext();
03220
03221
03222 LinearDocument ld(m_part, caretNode, offset);
03223
03224 ErgonomicEditableLineIterator it(ld.current(), cv->
origX);
03225
03226 moveIteratorByPage(ld, it, mindist, next);
03227
03228
int x, absx, absy;
03229 InlineBox *caretBox = nearestInlineBox(it, d->m_caretViewContext, x, absx, absy);
03230
03231 placeCaretOnLine(caretBox, x, absx, absy);
03232 }
03233
03234
void KHTMLView::moveCaretPrevWord()
03235 {
03236 moveCaretBy(
false, CaretByWord, 1);
03237 }
03238
03239
void KHTMLView::moveCaretNextWord()
03240 {
03241 moveCaretBy(
true, CaretByWord, 1);
03242 }
03243
03244
void KHTMLView::moveCaretPrevLine(
int n)
03245 {
03246 moveCaretByLine(
false, n);
03247 }
03248
03249
void KHTMLView::moveCaretNextLine(
int n)
03250 {
03251 moveCaretByLine(
true, n);
03252 }
03253
03254
void KHTMLView::moveCaretPrevPage()
03255 {
03256 moveCaretByPage(
false);
03257 }
03258
03259
void KHTMLView::moveCaretNextPage()
03260 {
03261 moveCaretByPage(
true);
03262 }
03263
03264
void KHTMLView::moveCaretToLineBegin()
03265 {
03266 moveCaretToLineBoundary(
false);
03267 }
03268
03269
void KHTMLView::moveCaretToLineEnd()
03270 {
03271 moveCaretToLineBoundary(
true);
03272 }
03273
03274
#endif // KHTML_NO_CARET
03275
03276
#undef DEBUG_CARETMODE