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