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