• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KHTML

  • sources
  • kde-4.14
  • kdelibs
  • khtml
khtmlview.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
4  * 1999 Lars Knoll <knoll@kde.org>
5  * 1999 Antti Koivisto <koivisto@kde.org>
6  * 2000-2004 Dirk Mueller <mueller@kde.org>
7  * 2003 Leo Savernik <l.savernik@aon.at>
8  * 2003-2008 Apple Computer, Inc.
9  * 2008 Allan Sandfeld Jensen <kde@carewolf.com>
10  * 2006-2008 Germain Garand <germain@ebooksfrance.org>
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB. If not, write to
24  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  */
27 
28 
29 #include "khtmlview.h"
30 
31 #include "khtmlview.moc"
32 
33 #include "khtml_part.h"
34 #include "khtml_events.h"
35 #ifdef Q_WS_X11
36 #include <qx11info_x11.h>
37 #endif
38 
39 #include "html/html_documentimpl.h"
40 #include "html/html_inlineimpl.h"
41 #include "html/html_formimpl.h"
42 #include "html/htmltokenizer.h"
43 #include "editing/editor.h"
44 #include "rendering/render_arena.h"
45 #include "rendering/render_canvas.h"
46 #include "rendering/render_frames.h"
47 #include "rendering/render_replaced.h"
48 #include "rendering/render_form.h"
49 #include "rendering/render_layer.h"
50 #include "rendering/render_line.h"
51 #include "rendering/render_table.h"
52 // removeme
53 #define protected public
54 #include "rendering/render_text.h"
55 #undef protected
56 #include "xml/dom2_eventsimpl.h"
57 #include "css/cssstyleselector.h"
58 #include "misc/loader.h"
59 #include "khtml_settings.h"
60 #include "khtml_printsettings.h"
61 
62 #include "khtmlpart_p.h"
63 
64 #include <kcursor.h>
65 #include <kdebug.h>
66 #include <kglobalsettings.h>
67 #include <kdialog.h>
68 #include <kiconloader.h>
69 #include <klocale.h>
70 #include <knotification.h>
71 #include <kdeprintdialog.h>
72 #include <kconfig.h>
73 #include <kstandarddirs.h>
74 #include <kstandardshortcut.h>
75 #include <kstringhandler.h>
76 #include <kconfiggroup.h>
77 
78 #include <QtGui/QBitmap>
79 #include <QtGui/QLabel>
80 #include <QtCore/QObject>
81 #include <QtGui/QPainter>
82 #include <QtCore/QHash>
83 #include <QtGui/QToolTip>
84 #include <QtCore/QString>
85 #include <QtGui/QTextDocument>
86 #include <QtCore/QTimer>
87 #include <QtCore/QAbstractEventDispatcher>
88 #include <QtCore/QVector>
89 #include <QtGui/QAbstractScrollArea>
90 #include <QtGui/QPrinter>
91 #include <QtGui/QPrintDialog>
92 
93 //#define DEBUG_FLICKER
94 
95 #include <limits.h>
96 #ifdef Q_WS_X11
97 #include <X11/Xlib.h>
98 #include <fixx11h.h>
99 #elif defined(Q_WS_WIN)
100 #include <windows.h>
101 #endif
102 
103 #if 0
104 namespace khtml {
105  void dumpLineBoxes(RenderFlow *flow);
106 }
107 #endif
108 
109 using namespace DOM;
110 using namespace khtml;
111 
112 #ifndef NDEBUG
113 static const int sFirstLayoutDelay = 520;
114 static const int sParsingLayoutsInterval = 380;
115 static const int sLayoutAttemptDelay = 300;
116 #else
117 static const int sFirstLayoutDelay = 280;
118 static const int sParsingLayoutsInterval = 320;
119 static const int sLayoutAttemptDelay = 200;
120 #endif
121 static const int sLayoutAttemptIncrement = 20;
122 static const int sParsingLayoutsIncrement = 60;
123 
124 static const int sSmoothScrollTime = 128;
125 static const int sSmoothScrollTick = 16;
126 static const int sSmoothScrollMinStaticPixels = 320*200;
127 
128 static const int sMaxMissedDeadlines = 12;
129 static const int sWayTooMany = -1;
130 
131 class KHTMLViewPrivate {
132  friend class KHTMLView;
133 public:
134 
135  enum PseudoFocusNodes {
136  PFNone,
137  PFTop,
138  PFBottom
139  };
140 
141  enum StaticBackgroundState {
142  SBNone = 0,
143  SBPartial,
144  SBFull
145  };
146 
147  enum CompletedState {
148  CSNone = 0,
149  CSFull,
150  CSActionPending
151  };
152 
153  KHTMLViewPrivate(KHTMLView* v)
154  : underMouse( 0 ), underMouseNonShared( 0 ), oldUnderMouse( 0 )
155  {
156  postponed_autorepeat = NULL;
157  scrollingFromWheelTimerId = 0;
158  smoothScrollMode = KHTMLView::SSMWhenEfficient;
159 
160  reset();
161  vpolicy = Qt::ScrollBarAsNeeded;
162  hpolicy = Qt::ScrollBarAsNeeded;
163  formCompletions=0;
164  prevScrollbarVisible = true;
165 
166  possibleTripleClick = false;
167  emitCompletedAfterRepaint = CSNone;
168  cursorIconWidget = 0;
169  cursorIconType = KHTMLView::LINK_NORMAL;
170  m_mouseScrollTimer = 0;
171  m_mouseScrollIndicator = 0;
172  contentsX = 0;
173  contentsY = 0;
174  view = v;
175  }
176  ~KHTMLViewPrivate()
177  {
178  delete formCompletions;
179  delete postponed_autorepeat;
180  if (underMouse)
181  underMouse->deref();
182  if (underMouseNonShared)
183  underMouseNonShared->deref();
184  if (oldUnderMouse)
185  oldUnderMouse->deref();
186 
187  delete cursorIconWidget;
188  delete m_mouseScrollTimer;
189  delete m_mouseScrollIndicator;
190  }
191  void reset()
192  {
193  if (underMouse)
194  underMouse->deref();
195  underMouse = 0;
196  if (underMouseNonShared)
197  underMouseNonShared->deref();
198  underMouseNonShared = 0;
199  if (oldUnderMouse)
200  oldUnderMouse->deref();
201  oldUnderMouse = 0;
202  linkPressed = false;
203  staticWidget = SBNone;
204  fixedObjectsCount = 0;
205  staticObjectsCount = 0;
206  tabMovePending = false;
207  lastTabbingDirection = true;
208  pseudoFocusNode = PFNone;
209  zoomLevel = 100;
210 #ifndef KHTML_NO_SCROLLBARS
211  //We don't turn off the toolbars here
212  //since if the user turns them
213  //off, then chances are they want them turned
214  //off always - even after a reset.
215 #else
216  vpolicy = ScrollBarAlwaysOff;
217  hpolicy = ScrollBarAlwaysOff;
218 #endif
219  scrollBarMoved = false;
220  contentsMoving = false;
221  ignoreWheelEvents = false;
222  scrollingFromWheel = QPoint(-1,-1);
223  borderX = 30;
224  borderY = 30;
225  steps = 0;
226  dx = dy = 0;
227  paged = false;
228  clickX = -1;
229  clickY = -1;
230  clickCount = 0;
231  isDoubleClick = false;
232  scrollingSelf = false;
233  delete postponed_autorepeat;
234  postponed_autorepeat = NULL;
235  layoutTimerId = 0;
236  repaintTimerId = 0;
237  scrollTimerId = 0;
238  scrollSuspended = false;
239  scrollSuspendPreActivate = false;
240  smoothScrolling = false;
241  smoothScrollModeIsDefault = true;
242  shouldSmoothScroll = false;
243  smoothScrollMissedDeadlines = 0;
244  hasFrameset = false;
245  complete = false;
246  firstLayoutPending = true;
247 #ifdef SPEED_DEBUG
248  firstRepaintPending = true;
249 #endif
250  needsFullRepaint = true;
251  dirtyLayout = false;
252  layoutSchedulingEnabled = true;
253  painting = false;
254  layoutCounter = 0;
255  layoutAttemptCounter = 0;
256  scheduledLayoutCounter = 0;
257  updateRegion = QRegion();
258  m_dialogsAllowed = true;
259  accessKeysActivated = false;
260  accessKeysPreActivate = false;
261 
262  // the view might have been built before the part it will be assigned to,
263  // so exceptionally, we need to directly ref/deref KHTMLGlobal to
264  // account for this transitory case.
265  KHTMLGlobal::ref();
266  accessKeysEnabled = KHTMLGlobal::defaultHTMLSettings()->accessKeysEnabled();
267  KHTMLGlobal::deref();
268 
269  emitCompletedAfterRepaint = CSNone;
270  m_mouseEventsTarget = 0;
271  m_clipHolder = 0;
272  }
273  void newScrollTimer(QWidget *view, int tid)
274  {
275  //kDebug(6000) << "newScrollTimer timer " << tid;
276  view->killTimer(scrollTimerId);
277  scrollTimerId = tid;
278  scrollSuspended = false;
279  }
280  enum ScrollDirection { ScrollLeft, ScrollRight, ScrollUp, ScrollDown };
281 
282  void adjustScroller(QWidget *view, ScrollDirection direction, ScrollDirection oppositedir)
283  {
284  static const struct { int msec, pixels; } timings [] = {
285  {320,1}, {224,1}, {160,1}, {112,1}, {80,1}, {56,1}, {40,1},
286  {28,1}, {20,1}, {20,2}, {20,3}, {20,4}, {20,6}, {20,8}, {0,0}
287  };
288  if (!scrollTimerId ||
289  (static_cast<int>(scrollDirection) != direction &&
290  (static_cast<int>(scrollDirection) != oppositedir || scrollSuspended))) {
291  scrollTiming = 6;
292  scrollBy = timings[scrollTiming].pixels;
293  scrollDirection = direction;
294  newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
295  } else if (scrollDirection == direction &&
296  timings[scrollTiming+1].msec && !scrollSuspended) {
297  scrollBy = timings[++scrollTiming].pixels;
298  newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
299  } else if (scrollDirection == oppositedir) {
300  if (scrollTiming) {
301  scrollBy = timings[--scrollTiming].pixels;
302  newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
303  }
304  }
305  scrollSuspended = false;
306  }
307 
308  bool haveZoom() const { return zoomLevel != 100; }
309 
310  void startScrolling()
311  {
312  smoothScrolling = true;
313  smoothScrollTimer.start(sSmoothScrollTick);
314  shouldSmoothScroll = false;
315  }
316 
317  void stopScrolling()
318  {
319  smoothScrollTimer.stop();
320  dx = dy = 0;
321  steps = 0;
322  updateContentsXY();
323  smoothScrolling = false;
324  shouldSmoothScroll = false;
325  }
326 
327  void updateContentsXY()
328  {
329  contentsX = QApplication::isRightToLeft() ?
330  view->horizontalScrollBar()->maximum()-view->horizontalScrollBar()->value() : view->horizontalScrollBar()->value();
331  contentsY = view->verticalScrollBar()->value();
332  }
333  void scrollAccessKeys(int dx, int dy)
334  {
335  QList<QLabel*> wl = qFindChildren<QLabel*>(view->widget(), "KHTMLAccessKey");
336  foreach(QLabel* w, wl) {
337  w->move( w->pos() + QPoint(dx, dy) );
338  }
339  }
340  void scrollExternalWidgets(int dx, int dy)
341  {
342  if (visibleWidgets.isEmpty())
343  return;
344 
345  QHashIterator<void*, QWidget*> it(visibleWidgets);
346  while (it.hasNext()) {
347  it.next();
348  it.value()->move( it.value()->pos() + QPoint(dx, dy) );
349  }
350  }
351 
352  NodeImpl *underMouse;
353  NodeImpl *underMouseNonShared;
354  NodeImpl *oldUnderMouse;
355 
356  // Do not adjust bitfield enums sizes.
357  // They are oversized because they are signed on some platforms.
358  bool tabMovePending:1;
359  bool lastTabbingDirection:1;
360  PseudoFocusNodes pseudoFocusNode:3;
361  bool scrollBarMoved:1;
362  bool contentsMoving:1;
363 
364  Qt::ScrollBarPolicy vpolicy;
365  Qt::ScrollBarPolicy hpolicy;
366  bool prevScrollbarVisible:1;
367  bool linkPressed:1;
368  bool ignoreWheelEvents:1;
369  StaticBackgroundState staticWidget: 3;
370  int staticObjectsCount;
371  int fixedObjectsCount;
372 
373  int zoomLevel;
374  int borderX, borderY;
375  int dx, dy;
376  int steps;
377  KConfig *formCompletions;
378 
379  int clickX, clickY, clickCount;
380  bool isDoubleClick;
381 
382  bool paged;
383 
384  bool scrollingSelf;
385  int contentsX, contentsY;
386  int layoutTimerId;
387  QKeyEvent* postponed_autorepeat;
388 
389  int repaintTimerId;
390  int scrollTimerId;
391  int scrollTiming;
392  int scrollBy;
393  ScrollDirection scrollDirection :3;
394  bool scrollSuspended :1;
395  bool scrollSuspendPreActivate :1;
396  KHTMLView::SmoothScrollingMode smoothScrollMode :3;
397  bool smoothScrolling :1;
398  bool smoothScrollModeIsDefault :1;
399  bool shouldSmoothScroll :1;
400  bool hasFrameset :1;
401  bool complete :1;
402  bool firstLayoutPending :1;
403 #ifdef SPEED_DEBUG
404  bool firstRepaintPending :1;
405 #endif
406  bool layoutSchedulingEnabled :1;
407  bool needsFullRepaint :1;
408  bool painting :1;
409  bool possibleTripleClick :1;
410  bool dirtyLayout :1;
411  bool m_dialogsAllowed :1;
412  short smoothScrollMissedDeadlines;
413  int layoutCounter;
414  int layoutAttemptCounter;
415  int scheduledLayoutCounter;
416  QRegion updateRegion;
417  QTimer smoothScrollTimer;
418  QTime smoothScrollStopwatch;
419  QHash<void*, QWidget*> visibleWidgets;
420  bool accessKeysEnabled;
421  bool accessKeysActivated;
422  bool accessKeysPreActivate;
423  CompletedState emitCompletedAfterRepaint;
424 
425  QLabel* cursorIconWidget;
426  KHTMLView::LinkCursor cursorIconType;
427 
428  // scrolling activated by MMB
429  short m_mouseScroll_byX;
430  short m_mouseScroll_byY;
431  QPoint scrollingFromWheel;
432  int scrollingFromWheelTimerId;
433  QTimer *m_mouseScrollTimer;
434  QWidget *m_mouseScrollIndicator;
435  QPointer<QWidget> m_mouseEventsTarget;
436  QStack<QRegion>* m_clipHolder;
437  KHTMLView* view;
438 };
439 
440 #ifndef QT_NO_TOOLTIP
441 
451 static bool findImageMapRect(HTMLImageElementImpl *img, const QPoint &scrollOfs,
452  const QPoint &p, QRect &r, QString &s)
453 {
454  HTMLMapElementImpl* map;
455  if (img && img->document()->isHTMLDocument() &&
456  (map = static_cast<HTMLDocumentImpl*>(img->document())->getMap(img->imageMap()))) {
457  RenderObject::NodeInfo info(true, false);
458  RenderObject *rend = img->renderer();
459  int ax, ay;
460  if (!rend || !rend->absolutePosition(ax, ay))
461  return false;
462  // we're a client side image map
463  bool inside = map->mapMouseEvent(p.x() - ax + scrollOfs.x(),
464  p.y() - ay + scrollOfs.y(), rend->contentWidth(),
465  rend->contentHeight(), info);
466  if (inside && info.URLElement()) {
467  HTMLAreaElementImpl *area = static_cast<HTMLAreaElementImpl *>(info.URLElement());
468  Q_ASSERT(area->id() == ID_AREA);
469  s = area->getAttribute(ATTR_TITLE).string();
470  QRegion reg = area->cachedRegion();
471  if (!s.isEmpty() && !reg.isEmpty()) {
472  r = reg.boundingRect();
473  r.translate(ax, ay);
474  return true;
475  }
476  }
477  }
478  return false;
479 }
480 
481 bool KHTMLView::event( QEvent* e )
482 {
483  switch ( e->type() ) {
484  case QEvent::ToolTip: {
485  QHelpEvent *he = static_cast<QHelpEvent*>(e);
486  QPoint p = he->pos();
487 
488  DOM::NodeImpl *node = d->underMouseNonShared;
489  QRect region;
490  while ( node ) {
491  if ( node->isElementNode() ) {
492  DOM::ElementImpl *e = static_cast<DOM::ElementImpl*>( node );
493  QRect r;
494  QString s;
495  bool found = false;
496  // for images, check if it is part of a client-side image map,
497  // and query the <area>s' title attributes, too
498  if (e->id() == ID_IMG && !e->getAttribute( ATTR_USEMAP ).isEmpty()) {
499  found = findImageMapRect(static_cast<HTMLImageElementImpl *>(e),
500  viewportToContents(QPoint(0, 0)), p, r, s);
501  }
502  if (!found) {
503  s = e->getAttribute(ATTR_TITLE).string().trimmed();
504  r = node->getRect();
505  }
506  region |= QRect( contentsToViewport( r.topLeft() ), r.size() );
507  if ( !s.isEmpty() ) {
508  QToolTip::showText( he->globalPos(),
509  Qt::convertFromPlainText( s, Qt::WhiteSpaceNormal ),
510  widget(), region );
511  break;
512  }
513  }
514  node = node->parentNode();
515  }
516  // Qt makes tooltip events happen nearly immediately when a preceding one was processed in the past few seconds.
517  // We don't want that feature to apply to web tootlips however, as it clashes with dhtml menus.
518  // So we'll just pretend we did not process that event.
519  return false;
520  }
521 
522  case QEvent::DragEnter:
523  case QEvent::DragMove:
524  case QEvent::DragLeave:
525  case QEvent::Drop:
526  // In Qt4, one needs to both call accept() on the DND event and return
527  // true on ::event for the candidate widget for the drop to be possible.
528  // Apps hosting us, such as konq, can do the former but not the later.
529  // We will do the second bit, as it's a no-op unless someone else explicitly
530  // accepts the event. We need to skip the scrollarea to do that,
531  // since it will just skip the events, both killing the drop, and
532  // not permitting us to forward it up the part hiearchy in our dragEnterEvent,
533  // etc. handlers
534  return QWidget::event(e);
535  case QEvent::StyleChange:
536  case QEvent::LayoutRequest: {
537  updateScrollBars();
538  return QAbstractScrollArea::event(e);
539  }
540  case QEvent::PaletteChange:
541  slotPaletteChanged();
542  return QScrollArea::event(e);
543  default:
544  return QScrollArea::event(e);
545  }
546 }
547 #endif
548 
549 KHTMLView::KHTMLView( KHTMLPart *part, QWidget *parent )
550  : QScrollArea( parent ), d( new KHTMLViewPrivate( this ) )
551 {
552  m_medium = "screen";
553 
554  m_part = part;
555 
556  QScrollArea::setVerticalScrollBarPolicy(d->vpolicy);
557  QScrollArea::setHorizontalScrollBarPolicy(d->hpolicy);
558 
559  init();
560  widget()->setMouseTracking(true);
561 }
562 
563 KHTMLView::~KHTMLView()
564 {
565  closeChildDialogs();
566  if (m_part)
567  {
568  DOM::DocumentImpl *doc = m_part->xmlDocImpl();
569  if (doc)
570  doc->detach();
571  }
572  delete d;
573 }
574 
575 void KHTMLView::setPart(KHTMLPart *part)
576 {
577  assert(part && !m_part);
578  m_part = part;
579 }
580 
581 void KHTMLView::init()
582 {
583  // Do not access the part here. It might not be fully constructed.
584 
585  setFrameStyle(QFrame::NoFrame);
586  setFocusPolicy(Qt::StrongFocus);
587  viewport()->setFocusProxy(this);
588 
589  _marginWidth = -1; // undefined
590  _marginHeight = -1;
591  _width = 0;
592  _height = 0;
593 
594  installEventFilter(this);
595 
596  setAcceptDrops(true);
597  if (!widget())
598  setWidget( new QWidget(this) );
599  widget()->setAttribute( Qt::WA_NoSystemBackground );
600 
601  // Do *not* remove this attribute frivolously.
602  // You might not notice a change of behaviour in Debug builds
603  // but removing opaque events will make QWidget::scroll fail horribly
604  // in Release builds.
605  widget()->setAttribute( Qt::WA_OpaquePaintEvent );
606 
607  verticalScrollBar()->setCursor( Qt::ArrowCursor );
608  horizontalScrollBar()->setCursor( Qt::ArrowCursor );
609 
610  connect(&d->smoothScrollTimer, SIGNAL(timeout()), this, SLOT(scrollTick()));
611 }
612 
613 void KHTMLView::resizeContentsToViewport()
614 {
615  QSize s = viewport()->size();
616  resizeContents(s.width(), s.height());
617 }
618 
619 
620 // called by KHTMLPart::clear()
621 void KHTMLView::clear()
622 {
623  if (d->accessKeysEnabled && d->accessKeysActivated)
624  accessKeysTimeout();
625  viewport()->unsetCursor();
626  if ( d->cursorIconWidget )
627  d->cursorIconWidget->hide();
628  if (d->smoothScrolling)
629  d->stopScrolling();
630  d->reset();
631  QAbstractEventDispatcher::instance()->unregisterTimers(this);
632  emit cleared();
633 
634  QScrollArea::setHorizontalScrollBarPolicy(d->hpolicy);
635  QScrollArea::setVerticalScrollBarPolicy(d->vpolicy);
636  verticalScrollBar()->setEnabled( false );
637  horizontalScrollBar()->setEnabled( false );
638 
639 }
640 
641 void KHTMLView::hideEvent(QHideEvent* e)
642 {
643  QScrollArea::hideEvent(e);
644 }
645 
646 void KHTMLView::showEvent(QShowEvent* e)
647 {
648  QScrollArea::showEvent(e);
649 }
650 
651 void KHTMLView::setMouseEventsTarget( QWidget* w )
652 {
653  d->m_mouseEventsTarget = w;
654 }
655 
656 QWidget* KHTMLView::mouseEventsTarget() const
657 {
658  return d->m_mouseEventsTarget;
659 }
660 
661 void KHTMLView::setClipHolder( QStack<QRegion>* ch )
662 {
663  d->m_clipHolder = ch;
664 }
665 
666 QStack<QRegion>* KHTMLView::clipHolder() const
667 {
668  return d->m_clipHolder;
669 }
670 
671 int KHTMLView::contentsWidth() const
672 {
673  return widget() ? widget()->width() : 0;
674 }
675 
676 int KHTMLView::contentsHeight() const
677 {
678  return widget() ? widget()->height() : 0;
679 }
680 
681 void KHTMLView::resizeContents(int w, int h)
682 {
683  if (!widget())
684  return;
685  widget()->resize(w, h);
686  if (!widget()->isVisible())
687  updateScrollBars();
688 }
689 
690 int KHTMLView::contentsX() const
691 {
692  return d->contentsX;
693 }
694 
695 int KHTMLView::contentsY() const
696 {
697  return d->contentsY;
698 }
699 
700 int KHTMLView::visibleWidth() const
701 {
702  if (m_kwp->isRedirected()) {
703  // our RenderWidget knows better
704  if (RenderWidget* rw = m_kwp->renderWidget()) {
705  int ret = rw->width()-rw->paddingLeft()-rw->paddingRight()-rw->borderLeft()-rw->borderRight();
706  if (verticalScrollBar()->isVisible()) {
707  ret -= verticalScrollBar()->sizeHint().width();
708  ret = qMax(0, ret);
709  }
710  return ret;
711  }
712  }
713  return viewport()->width();
714 }
715 
716 int KHTMLView::visibleHeight() const
717 {
718  if (m_kwp->isRedirected()) {
719  // our RenderWidget knows better
720  if (RenderWidget* rw = m_kwp->renderWidget()) {
721  int ret = rw->height()-rw->paddingBottom()-rw->paddingTop()-rw->borderTop()-rw->borderBottom();
722  if (horizontalScrollBar()->isVisible()) {
723  ret -= horizontalScrollBar()->sizeHint().height();
724  ret = qMax(0, ret);
725  }
726  return ret;
727  }
728  }
729  return viewport()->height();
730 }
731 
732 void KHTMLView::setContentsPos( int x, int y)
733 {
734  horizontalScrollBar()->setValue( QApplication::isRightToLeft() ?
735  horizontalScrollBar()->maximum()-x : x );
736  verticalScrollBar()->setValue( y );
737 }
738 
739 void KHTMLView::scrollBy(int x, int y)
740 {
741  if (d->scrollTimerId)
742  d->newScrollTimer(this, 0);
743  horizontalScrollBar()->setValue( horizontalScrollBar()->value()+x );
744  verticalScrollBar()->setValue( verticalScrollBar()->value()+y );
745 }
746 
747 QPoint KHTMLView::contentsToViewport(const QPoint& p) const
748 {
749  return QPoint(p.x()-contentsX(), p.y()-contentsY());
750 }
751 
752 void KHTMLView::contentsToViewport(int x, int y, int& cx, int& cy) const
753 {
754  QPoint p(x,y);
755  p = contentsToViewport(p);
756  cx = p.x();
757  cy = p.y();
758 }
759 
760 QPoint KHTMLView::viewportToContents(const QPoint& p) const
761 {
762  return QPoint(p.x()+contentsX(), p.y()+contentsY());
763 }
764 
765 void KHTMLView::viewportToContents(int x, int y, int& cx, int& cy) const
766 {
767  QPoint p(x,y);
768  p = viewportToContents(p);
769  cx = p.x();
770  cy = p.y();
771 }
772 
773 void KHTMLView::updateContents(int x, int y, int w, int h)
774 {
775  applyTransforms(x, y, w, h);
776  if (m_kwp->isRedirected()) {
777  QPoint off = m_kwp->absolutePos();
778  KHTMLView* pview = m_part->parentPart()->view();
779  pview->updateContents(x+off.x(), y+off.y(), w, h);
780  } else
781  widget()->update(x, y, w, h);
782 }
783 
784 void KHTMLView::updateContents( const QRect& r )
785 {
786  updateContents( r.x(), r.y(), r.width(), r.height() );
787 }
788 
789 void KHTMLView::repaintContents(int x, int y, int w, int h)
790 {
791  applyTransforms(x, y, w, h);
792  if (m_kwp->isRedirected()) {
793  QPoint off = m_kwp->absolutePos();
794  KHTMLView* pview = m_part->parentPart()->view();
795  pview->repaintContents(x+off.x(), y+off.y(), w, h);
796  } else
797  widget()->repaint(x, y, w, h);
798 }
799 
800 void KHTMLView::repaintContents( const QRect& r )
801 {
802  repaintContents( r.x(), r.y(), r.width(), r.height() );
803 }
804 
805 void KHTMLView::applyTransforms( int& x, int& y, int& w, int& h) const
806 {
807  if (d->haveZoom()) {
808  const int z = d->zoomLevel;
809  x = x*z/100;
810  y = y*z/100;
811  w = w*z/100;
812  h = h*z/100;
813  }
814  x -= contentsX();
815  y -= contentsY();
816 }
817 
818 void KHTMLView::revertTransforms( int& x, int& y, int& w, int& h) const
819 {
820  x += contentsX();
821  y += contentsY();
822  if (d->haveZoom()) {
823  const int z = d->zoomLevel;
824  x = x*100/z;
825  y = y*100/z;
826  w = w*100/z;
827  h = h*100/z;
828  }
829 }
830 
831 void KHTMLView::revertTransforms( int& x, int& y ) const
832 {
833  int dummy = 0;
834  revertTransforms(x, y, dummy, dummy);
835 }
836 
837 void KHTMLView::resizeEvent (QResizeEvent* /*e*/)
838 {
839  updateScrollBars();
840 
841  // If we didn't load anything, make white area as big as the view
842  if (!m_part->xmlDocImpl())
843  resizeContentsToViewport();
844 
845  // Viewport-dependent media queries may cause us to need completely different style information.
846  if (m_part->xmlDocImpl() && m_part->xmlDocImpl()->styleSelector()->affectedByViewportChange()) {
847  m_part->xmlDocImpl()->updateStyleSelector();
848  }
849 
850  if (d->layoutSchedulingEnabled)
851  layout();
852 
853  QApplication::sendPostedEvents(viewport(), QEvent::Paint);
854 
855  if ( m_part && m_part->xmlDocImpl() ) {
856  if (m_part->parentPart()) {
857  // sub-frame : queue the resize event until our toplevel is done layouting
858  khtml::ChildFrame *cf = m_part->parentPart()->frame( m_part );
859  if (cf && !cf->m_partContainerElement.isNull())
860  cf->m_partContainerElement.data()->postResizeEvent();
861  } else {
862  // toplevel : dispatch sub-frames'resize events before our own
863  HTMLPartContainerElementImpl::sendPostedResizeEvents();
864  m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false );
865  }
866  }
867 }
868 
869 void KHTMLView::paintEvent( QPaintEvent *e )
870 {
871  QRect r = e->rect();
872  QRect v(contentsX(), contentsY(), visibleWidth(), visibleHeight());
873  QPoint off(contentsX(),contentsY());
874  r.translate(off);
875  r = r.intersect(v);
876  if (!r.isValid() || r.isEmpty()) return;
877 
878  QPainter p(widget());
879  p.translate(-off);
880 
881  if (d->haveZoom()) {
882  p.scale( d->zoomLevel/100., d->zoomLevel/100.);
883 
884  r.setX(r.x()*100/d->zoomLevel);
885  r.setY(r.y()*100/d->zoomLevel);
886  r.setWidth(r.width()*100/d->zoomLevel);
887  r.setHeight(r.height()*100/d->zoomLevel);
888  r.adjust(-1,-1,1,1);
889  }
890  p.setClipRect(r);
891 
892  int ex = r.x();
893  int ey = r.y();
894  int ew = r.width();
895  int eh = r.height();
896 
897  if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
898  p.fillRect(ex, ey, ew, eh, palette().brush(QPalette::Active, QPalette::Base));
899  return;
900  } else if ( d->complete && static_cast<RenderCanvas*>(m_part->xmlDocImpl()->renderer())->needsLayout() ) {
901  // an external update request happens while we have a layout scheduled
902  unscheduleRelayout();
903  layout();
904  } else if (m_part->xmlDocImpl()->tokenizer()) {
905  m_part->xmlDocImpl()->tokenizer()->setNormalYieldDelay();
906  }
907 
908  if (d->painting) {
909  kDebug( 6000 ) << "WARNING: paintEvent reentered! ";
910  kDebug( 6000 ) << kBacktrace();
911  return;
912  }
913  d->painting = true;
914 
915  m_part->xmlDocImpl()->renderer()->layer()->paint(&p, r);
916 
917  if (d->hasFrameset) {
918  NodeImpl *body = static_cast<HTMLDocumentImpl*>(m_part->xmlDocImpl())->body();
919  if(body && body->renderer() && body->id() == ID_FRAMESET)
920  static_cast<RenderFrameSet*>(body->renderer())->paintFrameSetRules(&p, r);
921  else
922  d->hasFrameset = false;
923  }
924 
925  khtml::DrawContentsEvent event( &p, ex, ey, ew, eh );
926  QApplication::sendEvent( m_part, &event );
927 
928  if (d->contentsMoving && !d->smoothScrolling && widget()->underMouse()) {
929  QMouseEvent *tempEvent = new QMouseEvent( QEvent::MouseMove, widget()->mapFromGlobal( QCursor::pos() ),
930  Qt::NoButton, Qt::NoButton, Qt::NoModifier );
931  QApplication::postEvent(widget(), tempEvent);
932  }
933 #ifdef SPEED_DEBUG
934  if (d->firstRepaintPending && !m_part->parentPart()) {
935  kDebug(6080) << "FIRST PAINT:" << m_part->d->m_parsetime.elapsed();
936  }
937  d->firstRepaintPending = false;
938 #endif
939  d->painting = false;
940 }
941 
942 void KHTMLView::setMarginWidth(int w)
943 {
944  // make it update the rendering area when set
945  _marginWidth = w;
946 }
947 
948 void KHTMLView::setMarginHeight(int h)
949 {
950  // make it update the rendering area when set
951  _marginHeight = h;
952 }
953 
954 void KHTMLView::layout()
955 {
956  if( m_part && m_part->xmlDocImpl() ) {
957  DOM::DocumentImpl *document = m_part->xmlDocImpl();
958 
959  khtml::RenderCanvas* canvas = static_cast<khtml::RenderCanvas *>(document->renderer());
960  if ( !canvas ) return;
961 
962  d->layoutSchedulingEnabled=false;
963  d->dirtyLayout = true;
964 
965  // the reference object for the overflow property on canvas
966  RenderObject * ref = 0;
967  RenderObject* root = document->documentElement() ? document->documentElement()->renderer() : 0;
968 
969  if (document->isHTMLDocument()) {
970  NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
971  if(body && body->renderer() && body->id() == ID_FRAMESET) {
972  QScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
973  QScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
974  body->renderer()->setNeedsLayout(true);
975  d->hasFrameset = true;
976  }
977  else if (root) // only apply body's overflow to canvas if root has a visible overflow
978  ref = (!body || root->style()->hidesOverflow()) ? root : body->renderer();
979  } else {
980  ref = root;
981  }
982  if (ref) {
983  if( ref->style()->overflowX() == OHIDDEN ) {
984  if (d->hpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
985  } else if (ref->style()->overflowX() == OSCROLL ) {
986  if (d->hpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
987  } else if (horizontalScrollBarPolicy() != d->hpolicy) {
988  QScrollArea::setHorizontalScrollBarPolicy(d->hpolicy);
989  }
990  if ( ref->style()->overflowY() == OHIDDEN ) {
991  if (d->vpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
992  } else if (ref->style()->overflowY() == OSCROLL ) {
993  if (d->vpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
994  } else if (verticalScrollBarPolicy() != d->vpolicy) {
995  QScrollArea::setVerticalScrollBarPolicy(d->vpolicy);
996  }
997  }
998  d->needsFullRepaint = d->firstLayoutPending;
999  if (_height != visibleHeight() || _width != visibleWidth()) {;
1000  d->needsFullRepaint = true;
1001  _height = visibleHeight();
1002  _width = visibleWidth();
1003  }
1004 
1005  canvas->layout();
1006 
1007  emit finishedLayout();
1008  if (d->firstLayoutPending) {
1009  // make sure firstLayoutPending is set to false now in case this layout
1010  // wasn't scheduled
1011  d->firstLayoutPending = false;
1012  verticalScrollBar()->setEnabled( true );
1013  horizontalScrollBar()->setEnabled( true );
1014  }
1015  d->layoutCounter++;
1016 
1017  if (d->accessKeysEnabled && d->accessKeysActivated) {
1018  emit hideAccessKeys();
1019  displayAccessKeys();
1020  }
1021  }
1022  else
1023  _width = visibleWidth();
1024 
1025  if (d->layoutTimerId)
1026  killTimer(d->layoutTimerId);
1027  d->layoutTimerId = 0;
1028  d->layoutSchedulingEnabled=true;
1029 }
1030 
1031 void KHTMLView::closeChildDialogs()
1032 {
1033  QList<QDialog *> dlgs = findChildren<QDialog *>();
1034  foreach (QDialog *dlg, dlgs)
1035  {
1036  KDialog* dlgbase = dynamic_cast<KDialog*>( dlg );
1037  if ( dlgbase ) {
1038  if ( dlgbase->testAttribute( Qt::WA_ShowModal ) ) {
1039  kDebug(6000) << "closeChildDialogs: closing dialog " << dlgbase;
1040  // close() ends up calling QButton::animateClick, which isn't immediate
1041  // we need something the exits the event loop immediately (#49068)
1042  dlgbase->reject();
1043  }
1044  }
1045  else
1046  {
1047  kWarning() << "closeChildDialogs: not a KDialog! Don't use QDialogs in KDE! " << static_cast<QWidget*>(dlg);
1048  static_cast<QWidget*>(dlg)->hide();
1049  }
1050  }
1051  d->m_dialogsAllowed = false;
1052 }
1053 
1054 bool KHTMLView::dialogsAllowed() {
1055  bool allowed = d->m_dialogsAllowed;
1056  KHTMLPart* p = m_part->parentPart();
1057  if (p && p->view())
1058  allowed &= p->view()->dialogsAllowed();
1059  return allowed;
1060 }
1061 
1062 void KHTMLView::closeEvent( QCloseEvent* ev )
1063 {
1064  closeChildDialogs();
1065  QScrollArea::closeEvent( ev );
1066 }
1067 
1068 void KHTMLView::setZoomLevel(int percent)
1069 {
1070  percent = percent < 20 ? 20 : (percent > 800 ? 800 : percent);
1071  int oldpercent = d->zoomLevel;
1072  d->zoomLevel = percent;
1073  if (percent != oldpercent) {
1074  if (d->layoutSchedulingEnabled)
1075  layout();
1076  widget()->update();
1077  }
1078 }
1079 
1080 int KHTMLView::zoomLevel() const
1081 {
1082  return d->zoomLevel;
1083 }
1084 
1085 void KHTMLView::setSmoothScrollingMode( SmoothScrollingMode m )
1086 {
1087  d->smoothScrollMode = m;
1088  d->smoothScrollModeIsDefault = false;
1089  if (d->smoothScrolling && !m)
1090  d->stopScrolling();
1091 }
1092 
1093 void KHTMLView::setSmoothScrollingModeDefault( SmoothScrollingMode m )
1094 {
1095  // check for manual override
1096  if (!d->smoothScrollModeIsDefault)
1097  return;
1098  d->smoothScrollMode = m;
1099  if (d->smoothScrolling && !m)
1100  d->stopScrolling();
1101 }
1102 
1103 KHTMLView::SmoothScrollingMode KHTMLView::smoothScrollingMode( ) const
1104 {
1105  return d->smoothScrollMode;
1106 }
1107 
1108 //
1109 // Event Handling
1110 //
1112 
1113 void KHTMLView::mousePressEvent( QMouseEvent *_mouse )
1114 {
1115  if (!m_part->xmlDocImpl()) return;
1116  if (d->possibleTripleClick && ( _mouse->button() & Qt::MouseButtonMask ) == Qt::LeftButton)
1117  {
1118  mouseDoubleClickEvent( _mouse ); // it handles triple clicks too
1119  return;
1120  }
1121 
1122  int xm = _mouse->x();
1123  int ym = _mouse->y();
1124  revertTransforms(xm, ym);
1125 
1126  // kDebug( 6000 ) << "mousePressEvent: viewport=("<<_mouse->x()-contentsX()<<"/"<<_mouse->y()-contentsY()<<"), contents=(" << xm << "/" << ym << ")\n";
1127 
1128  d->isDoubleClick = false;
1129 
1130  DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MousePress );
1131  m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
1132 
1133  //kDebug(6000) << "innerNode="<<mev.innerNode.nodeName().string();
1134 
1135  if ( (_mouse->button() == Qt::MidButton) &&
1136  !m_part->d->m_bOpenMiddleClick && !d->m_mouseScrollTimer &&
1137  mev.url.isNull() && (mev.innerNode.elementId() != ID_INPUT) ) {
1138  QPoint point = mapFromGlobal( _mouse->globalPos() );
1139 
1140  d->m_mouseScroll_byX = 0;
1141  d->m_mouseScroll_byY = 0;
1142 
1143  d->m_mouseScrollTimer = new QTimer( this );
1144  connect( d->m_mouseScrollTimer, SIGNAL(timeout()), this, SLOT(slotMouseScrollTimer()) );
1145 
1146  if ( !d->m_mouseScrollIndicator ) {
1147  QPixmap pixmap( 48, 48 ), icon;
1148  pixmap.fill( QColor( qRgba( 127, 127, 127, 127 ) ) );
1149 
1150  QPainter p( &pixmap );
1151  QStyleOption option;
1152 
1153  option.rect.setRect( 16, 0, 16, 16 );
1154  QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowUp, &option, &p );
1155  option.rect.setRect( 0, 16, 16, 16 );
1156  QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowLeft, &option, &p );
1157  option.rect.setRect( 16, 32, 16, 16 );
1158  QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowDown, &option, &p );
1159  option.rect.setRect( 32, 16, 16, 16 );
1160  QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowRight, &option, &p );
1161  p.drawEllipse( 23, 23, 2, 2 );
1162 
1163  d->m_mouseScrollIndicator = new QWidget( this );
1164  d->m_mouseScrollIndicator->setFixedSize( 48, 48 );
1165  QPalette palette;
1166  palette.setBrush( d->m_mouseScrollIndicator->backgroundRole(), QBrush( pixmap ) );
1167  d->m_mouseScrollIndicator->setPalette( palette );
1168  }
1169  d->m_mouseScrollIndicator->move( point.x()-24, point.y()-24 );
1170 
1171  bool hasHorBar = visibleWidth() < contentsWidth();
1172  bool hasVerBar = visibleHeight() < contentsHeight();
1173 
1174  KConfigGroup cg( KGlobal::config(), "HTML Settings" );
1175  if ( cg.readEntry( "ShowMouseScrollIndicator", true ) ) {
1176  d->m_mouseScrollIndicator->show();
1177  d->m_mouseScrollIndicator->unsetCursor();
1178 
1179  QBitmap mask = d->m_mouseScrollIndicator->palette().brush(d->m_mouseScrollIndicator->backgroundRole()).texture().createHeuristicMask( true );
1180 
1181  if ( hasHorBar && !hasVerBar ) {
1182  QBitmap bm( 16, 16 );
1183  bm.clear();
1184  QPainter painter( &mask );
1185  painter.drawPixmap( QRectF( 16, 0, bm.width(), bm.height() ), bm, bm.rect() );
1186  painter.drawPixmap( QRectF( 16, 32, bm.width(), bm.height() ), bm, bm.rect() );
1187  d->m_mouseScrollIndicator->setCursor( Qt::SizeHorCursor );
1188  }
1189  else if ( !hasHorBar && hasVerBar ) {
1190  QBitmap bm( 16, 16 );
1191  bm.clear();
1192  QPainter painter( &mask );
1193  painter.drawPixmap( QRectF( 0, 16, bm.width(), bm.height() ), bm, bm.rect() );
1194  painter.drawPixmap( QRectF( 32, 16, bm.width(), bm.height() ), bm, bm.rect() );
1195  d->m_mouseScrollIndicator->setCursor( Qt::SizeVerCursor );
1196  }
1197  else
1198  d->m_mouseScrollIndicator->setCursor( Qt::SizeAllCursor );
1199 
1200  d->m_mouseScrollIndicator->setMask( mask );
1201  }
1202  else {
1203  if ( hasHorBar && !hasVerBar )
1204  viewport()->setCursor( Qt::SizeHorCursor );
1205  else if ( !hasHorBar && hasVerBar )
1206  viewport()->setCursor( Qt::SizeVerCursor );
1207  else
1208  viewport()->setCursor( Qt::SizeAllCursor );
1209  }
1210 
1211  return;
1212  }
1213  else if ( d->m_mouseScrollTimer ) {
1214  delete d->m_mouseScrollTimer;
1215  d->m_mouseScrollTimer = 0;
1216 
1217  if ( d->m_mouseScrollIndicator )
1218  d->m_mouseScrollIndicator->hide();
1219  }
1220 
1221  if (d->clickCount > 0 &&
1222  QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
1223  d->clickCount++;
1224  else {
1225  d->clickCount = 1;
1226  d->clickX = xm;
1227  d->clickY = ym;
1228  }
1229 
1230  bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
1231  d->clickCount,_mouse,true,DOM::NodeImpl::MousePress);
1232 
1233  if (!swallowEvent) {
1234  emit m_part->nodeActivated(mev.innerNode);
1235 
1236  khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
1237  QApplication::sendEvent( m_part, &event );
1238  // we might be deleted after this
1239  }
1240 }
1241 
1242 void KHTMLView::mouseDoubleClickEvent( QMouseEvent *_mouse )
1243 {
1244  if(!m_part->xmlDocImpl()) return;
1245 
1246  int xm = _mouse->x();
1247  int ym = _mouse->y();
1248  revertTransforms(xm, ym);
1249 
1250  // kDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym;
1251 
1252  d->isDoubleClick = true;
1253 
1254  DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MouseDblClick );
1255  m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
1256 
1257  // We do the same thing as mousePressEvent() here, since the DOM does not treat
1258  // single and double-click events as separate (only the detail, i.e. number of clicks differs)
1259  if (d->clickCount > 0 &&
1260  QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
1261  d->clickCount++;
1262  else { // shouldn't happen, if Qt has the same criterias for double clicks.
1263  d->clickCount = 1;
1264  d->clickX = xm;
1265  d->clickY = ym;
1266  }
1267  bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
1268  d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick);
1269 
1270  if (!swallowEvent) {
1271  khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode, d->clickCount );
1272  QApplication::sendEvent( m_part, &event );
1273  }
1274 
1275  d->possibleTripleClick=true;
1276  QTimer::singleShot(QApplication::doubleClickInterval(),this,SLOT(tripleClickTimeout()));
1277 }
1278 
1279 void KHTMLView::tripleClickTimeout()
1280 {
1281  d->possibleTripleClick = false;
1282  d->clickCount = 0;
1283 }
1284 
1285 static bool targetOpensNewWindow(KHTMLPart *part, QString target)
1286 {
1287  if (!target.isEmpty() && (target.toLower() != "_top") &&
1288  (target.toLower() != "_self") && (target.toLower() != "_parent")) {
1289  if (target.toLower() == "_blank")
1290  return true;
1291  else {
1292  while (part->parentPart())
1293  part = part->parentPart();
1294  if (!part->frameExists(target))
1295  return true;
1296  }
1297  }
1298  return false;
1299 }
1300 
1301 void KHTMLView::mouseMoveEvent( QMouseEvent * _mouse )
1302 {
1303  if ( d->m_mouseScrollTimer ) {
1304  QPoint point = mapFromGlobal( _mouse->globalPos() );
1305 
1306  int deltaX = point.x() - d->m_mouseScrollIndicator->x() - 24;
1307  int deltaY = point.y() - d->m_mouseScrollIndicator->y() - 24;
1308 
1309  (deltaX > 0) ? d->m_mouseScroll_byX = 1 : d->m_mouseScroll_byX = -1;
1310  (deltaY > 0) ? d->m_mouseScroll_byY = 1 : d->m_mouseScroll_byY = -1;
1311 
1312  double adX = qAbs(deltaX)/30.0;
1313  double adY = qAbs(deltaY)/30.0;
1314 
1315  d->m_mouseScroll_byX = qMax(qMin(d->m_mouseScroll_byX * int(adX*adX), SHRT_MAX), SHRT_MIN);
1316  d->m_mouseScroll_byY = qMax(qMin(d->m_mouseScroll_byY * int(adY*adY), SHRT_MAX), SHRT_MIN);
1317 
1318  if (d->m_mouseScroll_byX == 0 && d->m_mouseScroll_byY == 0) {
1319  d->m_mouseScrollTimer->stop();
1320  }
1321  else if (!d->m_mouseScrollTimer->isActive()) {
1322  d->m_mouseScrollTimer->start( 20 );
1323  }
1324  }
1325 
1326  if(!m_part->xmlDocImpl()) return;
1327 
1328  int xm = _mouse->x();
1329  int ym = _mouse->y();
1330  revertTransforms(xm, ym);
1331 
1332  DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MouseMove );
1333  // Do not modify :hover/:active state while mouse is pressed.
1334  m_part->xmlDocImpl()->prepareMouseEvent( _mouse->buttons() /*readonly ?*/, xm, ym, &mev );
1335 
1336  // kDebug(6000) << "mouse move: " << _mouse->pos()
1337  // << " button " << _mouse->button()
1338  // << " state " << _mouse->state() << endl;
1339 
1340  DOM::NodeImpl* target = mev.innerNode.handle();
1341  DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode();
1342 
1343  // a widget may be the real target of this event (e.g. if a scrollbar's slider is being moved)
1344  if (d->m_mouseEventsTarget && fn && fn->renderer() && fn->renderer()->isWidget())
1345  target = fn;
1346 
1347  bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,target,mev.innerNonSharedNode.handle(),false,
1348  0,_mouse,true,DOM::NodeImpl::MouseMove);
1349 
1350  if (d->clickCount > 0 &&
1351  QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() > QApplication::startDragDistance()) {
1352  d->clickCount = 0; // moving the mouse outside the threshold invalidates the click
1353  }
1354 
1355  khtml::RenderObject* r = target ? target->renderer() : 0;
1356  bool setCursor = true;
1357  bool forceDefault = false;
1358  if (r && r->isWidget()) {
1359  RenderWidget* rw = static_cast<RenderWidget*>(r);
1360  KHTMLWidget* kw = qobject_cast<KHTMLView*>(rw->widget())? dynamic_cast<KHTMLWidget*>(rw->widget()) : 0;
1361  if (kw && kw->m_kwp->isRedirected())
1362  setCursor = false;
1363  else if (QLineEdit* le = qobject_cast<QLineEdit*>(rw->widget())) {
1364  QList<QWidget*> wl = qFindChildren<QWidget *>( le, "KLineEditButton" );
1365  // force arrow cursor above lineedit clear button
1366  foreach (QWidget*w, wl) {
1367  if (w->underMouse()) {
1368  forceDefault = true;
1369  break;
1370  }
1371  }
1372  }
1373  else if (QTextEdit* te = qobject_cast<QTextEdit*>(rw->widget())) {
1374  if (te->verticalScrollBar()->underMouse() || te->horizontalScrollBar()->underMouse())
1375  forceDefault = true;
1376  }
1377  }
1378  khtml::RenderStyle* style = (r && r->style()) ? r->style() : 0;
1379  QCursor c;
1380  LinkCursor linkCursor = LINK_NORMAL;
1381  switch (!forceDefault ? (style ? style->cursor() : CURSOR_AUTO) : CURSOR_DEFAULT) {
1382  case CURSOR_AUTO:
1383  if ( r && r->isText() && ((m_part->d->m_bMousePressed && m_part->d->editor_context.m_beganSelectingText) ||
1384  !r->isPointInsideSelection(xm, ym, m_part->caret())) )
1385  c = QCursor(Qt::IBeamCursor);
1386  if ( mev.url.length() && m_part->settings()->changeCursor() ) {
1387  c = m_part->urlCursor();
1388  if (mev.url.string().startsWith("mailto:") && mev.url.string().indexOf('@')>0)
1389  linkCursor = LINK_MAILTO;
1390  else
1391  if ( targetOpensNewWindow( m_part, mev.target.string() ) )
1392  linkCursor = LINK_NEWWINDOW;
1393  }
1394 
1395  if (r && r->isFrameSet() && !static_cast<RenderFrameSet*>(r)->noResize())
1396  c = QCursor(static_cast<RenderFrameSet*>(r)->cursorShape());
1397 
1398  break;
1399  case CURSOR_CROSS:
1400  c = QCursor(Qt::CrossCursor);
1401  break;
1402  case CURSOR_POINTER:
1403  c = m_part->urlCursor();
1404  if (mev.url.string().startsWith("mailto:") && mev.url.string().indexOf('@')>0)
1405  linkCursor = LINK_MAILTO;
1406  else
1407  if ( targetOpensNewWindow( m_part, mev.target.string() ) )
1408  linkCursor = LINK_NEWWINDOW;
1409  break;
1410  case CURSOR_PROGRESS:
1411  c = QCursor(Qt::BusyCursor); // working_cursor
1412  break;
1413  case CURSOR_MOVE:
1414  case CURSOR_ALL_SCROLL:
1415  c = QCursor(Qt::SizeAllCursor);
1416  break;
1417  case CURSOR_E_RESIZE:
1418  case CURSOR_W_RESIZE:
1419  case CURSOR_EW_RESIZE:
1420  c = QCursor(Qt::SizeHorCursor);
1421  break;
1422  case CURSOR_N_RESIZE:
1423  case CURSOR_S_RESIZE:
1424  case CURSOR_NS_RESIZE:
1425  c = QCursor(Qt::SizeVerCursor);
1426  break;
1427  case CURSOR_NE_RESIZE:
1428  case CURSOR_SW_RESIZE:
1429  case CURSOR_NESW_RESIZE:
1430  c = QCursor(Qt::SizeBDiagCursor);
1431  break;
1432  case CURSOR_NW_RESIZE:
1433  case CURSOR_SE_RESIZE:
1434  case CURSOR_NWSE_RESIZE:
1435  c = QCursor(Qt::SizeFDiagCursor);
1436  break;
1437  case CURSOR_TEXT:
1438  c = QCursor(Qt::IBeamCursor);
1439  break;
1440  case CURSOR_WAIT:
1441  c = QCursor(Qt::WaitCursor);
1442  break;
1443  case CURSOR_HELP:
1444  c = QCursor(Qt::WhatsThisCursor);
1445  break;
1446  case CURSOR_DEFAULT:
1447  break;
1448  case CURSOR_NONE:
1449  case CURSOR_NOT_ALLOWED:
1450  c = QCursor(Qt::ForbiddenCursor);
1451  break;
1452  case CURSOR_ROW_RESIZE:
1453  c = QCursor(Qt::SplitVCursor);
1454  break;
1455  case CURSOR_COL_RESIZE:
1456  c = QCursor(Qt::SplitHCursor);
1457  break;
1458  case CURSOR_VERTICAL_TEXT:
1459  case CURSOR_CONTEXT_MENU:
1460  case CURSOR_NO_DROP:
1461  case CURSOR_CELL:
1462  case CURSOR_COPY:
1463  case CURSOR_ALIAS:
1464  c = QCursor(Qt::ArrowCursor);
1465  break;
1466  }
1467 
1468  if (!setCursor && style && style->cursor() != CURSOR_AUTO)
1469  setCursor = true;
1470 
1471  QWidget* vp = viewport();
1472  for (KHTMLPart* p = m_part; p; p = p->parentPart())
1473  if (!p->parentPart())
1474  vp = p->view()->viewport();
1475  if ( setCursor && vp->cursor().handle() != c.handle() ) {
1476  if( c.shape() == Qt::ArrowCursor) {
1477  for (KHTMLPart* p = m_part; p; p = p->parentPart())
1478  p->view()->viewport()->unsetCursor();
1479  }
1480  else {
1481  vp->setCursor( c );
1482  }
1483  }
1484 
1485  if ( linkCursor!=LINK_NORMAL && isVisible() && hasFocus() ) {
1486 #ifdef Q_WS_X11
1487 
1488  if( !d->cursorIconWidget ) {
1489 #ifdef Q_WS_X11
1490  d->cursorIconWidget = new QLabel( 0, Qt::X11BypassWindowManagerHint );
1491  XSetWindowAttributes attr;
1492  attr.save_under = True;
1493  XChangeWindowAttributes( QX11Info::display(), d->cursorIconWidget->winId(), CWSaveUnder, &attr );
1494 #else
1495  d->cursorIconWidget = new QLabel( NULL, NULL );
1496  //TODO
1497 #endif
1498  }
1499 
1500  // Update the pixmap if need be.
1501  if (linkCursor != d->cursorIconType) {
1502  d->cursorIconType = linkCursor;
1503  QString cursorIcon;
1504  switch (linkCursor)
1505  {
1506  case LINK_MAILTO: cursorIcon = "mail-message-new"; break;
1507  case LINK_NEWWINDOW: cursorIcon = "window-new"; break;
1508  default: cursorIcon = "dialog-error"; break;
1509  }
1510 
1511  QPixmap icon_pixmap = KHTMLGlobal::iconLoader()->loadIcon( cursorIcon, KIconLoader::Small, 0, KIconLoader::DefaultState, QStringList(), 0, true );
1512 
1513  d->cursorIconWidget->resize( icon_pixmap.width(), icon_pixmap.height());
1514  d->cursorIconWidget->setMask( icon_pixmap.createMaskFromColor(Qt::transparent));
1515  d->cursorIconWidget->setPixmap( icon_pixmap);
1516  d->cursorIconWidget->update();
1517  }
1518 
1519  QPoint c_pos = QCursor::pos();
1520  d->cursorIconWidget->move( c_pos.x() + 15, c_pos.y() + 15 );
1521 #ifdef Q_WS_X11
1522  XRaiseWindow( QX11Info::display(), d->cursorIconWidget->winId());
1523  QApplication::flush();
1524 #elif defined(Q_WS_WIN)
1525  SetWindowPos( d->cursorIconWidget->winId(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
1526 #else
1527  //TODO?
1528 #endif
1529  d->cursorIconWidget->show();
1530 #endif
1531  }
1532  else if ( d->cursorIconWidget )
1533  d->cursorIconWidget->hide();
1534 
1535  if (r && r->isWidget()) {
1536  _mouse->ignore();
1537  }
1538 
1539  if (!swallowEvent) {
1540  khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
1541  QApplication::sendEvent( m_part, &event );
1542  }
1543 }
1544 
1545 void KHTMLView::mouseReleaseEvent( QMouseEvent * _mouse )
1546 {
1547  bool swallowEvent = false;
1548 
1549  int xm = _mouse->x();
1550  int ym = _mouse->y();
1551  revertTransforms(xm, ym);
1552 
1553  DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MouseRelease );
1554 
1555  if ( m_part->xmlDocImpl() )
1556  {
1557  m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
1558 
1559  DOM::NodeImpl* target = mev.innerNode.handle();
1560  DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode();
1561 
1562  // a widget may be the real target of this event (e.g. if a scrollbar's slider is being moved)
1563  if (d->m_mouseEventsTarget && fn && fn->renderer() && fn->renderer()->isWidget())
1564  target = fn;
1565 
1566  swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,target,mev.innerNonSharedNode.handle(),true,
1567  d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease);
1568 
1569  // clear our sticky event target on any mouseRelease event
1570  if (d->m_mouseEventsTarget)
1571  d->m_mouseEventsTarget = 0;
1572 
1573  if (d->clickCount > 0 &&
1574  QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance()) {
1575  QMouseEvent me(d->isDoubleClick ? QEvent::MouseButtonDblClick : QEvent::MouseButtonRelease,
1576  _mouse->pos(), _mouse->button(), _mouse->buttons(), _mouse->modifiers());
1577  dispatchMouseEvent(EventImpl::CLICK_EVENT, mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
1578  d->clickCount, &me, true, DOM::NodeImpl::MouseRelease);
1579  }
1580 
1581  khtml::RenderObject* r = target ? target->renderer() : 0;
1582  if (r && r->isWidget())
1583  _mouse->ignore();
1584  }
1585 
1586  if (!swallowEvent) {
1587  khtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
1588  QApplication::sendEvent( m_part, &event );
1589  }
1590 }
1591 
1592 // returns true if event should be swallowed
1593 bool KHTMLView::dispatchKeyEvent( QKeyEvent *_ke )
1594 {
1595  if (!m_part->xmlDocImpl())
1596  return false;
1597  // Pressing and releasing a key should generate keydown, keypress and keyup events
1598  // Holding it down should generated keydown, keypress (repeatedly) and keyup events
1599  // The problem here is that Qt generates two autorepeat events (keyrelease+keypress)
1600  // for autorepeating, while DOM wants only one autorepeat event (keypress), so one
1601  // of the Qt events shouldn't be passed to DOM, but it should be still filtered
1602  // out if DOM would filter the autorepeat event. Additional problem is that Qt keyrelease
1603  // events don't have text() set (Qt bug?), so DOM often would ignore the keypress event
1604  // if it was created using Qt keyrelease, but Qt autorepeat keyrelease comes
1605  // before Qt autorepeat keypress (i.e. problem whether to filter it out or not).
1606  // The solution is to filter out and postpone the Qt autorepeat keyrelease until
1607  // the following Qt keypress event comes. If DOM accepts the DOM keypress event,
1608  // the postponed event will be simply discarded. If not, it will be passed to keyPressEvent()
1609  // again, and here it will be ignored.
1610  //
1611  // Qt: Press | Release(autorepeat) Press(autorepeat) etc. | Release
1612  // DOM: Down + Press | (nothing) Press | Up
1613 
1614  // It's also possible to get only Releases. E.g. the release of alt-tab,
1615  // or when the keypresses get captured by an accel.
1616 
1617  if( _ke == d->postponed_autorepeat ) // replayed event
1618  {
1619  return false;
1620  }
1621 
1622  if( _ke->type() == QEvent::KeyPress )
1623  {
1624  if( !_ke->isAutoRepeat())
1625  {
1626  bool ret = dispatchKeyEventHelper( _ke, false ); // keydown
1627  // don't send keypress even if keydown was blocked, like IE (and unlike Mozilla)
1628  if( !ret && dispatchKeyEventHelper( _ke, true )) // keypress
1629  ret = true;
1630  return ret;
1631  }
1632  else // autorepeat
1633  {
1634  bool ret = dispatchKeyEventHelper( _ke, true ); // keypress
1635  if( !ret && d->postponed_autorepeat )
1636  keyPressEvent( d->postponed_autorepeat );
1637  delete d->postponed_autorepeat;
1638  d->postponed_autorepeat = NULL;
1639  return ret;
1640  }
1641  }
1642  else // QEvent::KeyRelease
1643  {
1644  // Discard postponed "autorepeat key-release" events that didn't see
1645  // a keypress after them (e.g. due to QAccel)
1646  delete d->postponed_autorepeat;
1647  d->postponed_autorepeat = 0;
1648 
1649  if( !_ke->isAutoRepeat()) {
1650  return dispatchKeyEventHelper( _ke, false ); // keyup
1651  }
1652  else
1653  {
1654  d->postponed_autorepeat = new QKeyEvent( _ke->type(), _ke->key(), _ke->modifiers(),
1655  _ke->text(), _ke->isAutoRepeat(), _ke->count());
1656  if( _ke->isAccepted())
1657  d->postponed_autorepeat->accept();
1658  else
1659  d->postponed_autorepeat->ignore();
1660  return true;
1661  }
1662  }
1663 }
1664 
1665 // returns true if event should be swallowed
1666 bool KHTMLView::dispatchKeyEventHelper( QKeyEvent *_ke, bool keypress )
1667 {
1668  DOM::NodeImpl* keyNode = m_part->xmlDocImpl()->focusNode();
1669  if (keyNode) {
1670  return keyNode->dispatchKeyEvent(_ke, keypress);
1671  } else { // no focused node, send to document
1672  return m_part->xmlDocImpl()->dispatchKeyEvent(_ke, keypress);
1673  }
1674 }
1675 
1676 void KHTMLView::keyPressEvent( QKeyEvent *_ke )
1677 {
1678  // If CTRL was hit, be prepared for access keys
1679  if (d->accessKeysEnabled && _ke->key() == Qt::Key_Control && !(_ke->modifiers() & ~Qt::ControlModifier) && !d->accessKeysActivated)
1680  {
1681  d->accessKeysPreActivate=true;
1682  _ke->accept();
1683  return;
1684  }
1685 
1686  if (_ke->key() == Qt::Key_Shift && !(_ke->modifiers() & ~Qt::ShiftModifier))
1687  d->scrollSuspendPreActivate=true;
1688 
1689  // accesskey handling needs to be done before dispatching, otherwise e.g. lineedits
1690  // may eat the event
1691 
1692  if (d->accessKeysEnabled && d->accessKeysActivated)
1693  {
1694  int state = ( _ke->modifiers() & ( Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier ));
1695  if ( state==0 || state==Qt::ShiftModifier ) {
1696  if (_ke->key() != Qt::Key_Shift)
1697  accessKeysTimeout();
1698  handleAccessKey( _ke );
1699  _ke->accept();
1700  return;
1701  }
1702  accessKeysTimeout();
1703  _ke->accept();
1704  return;
1705  }
1706 
1707  if ( dispatchKeyEvent( _ke )) {
1708  // If either keydown or keypress was accepted by a widget, or canceled by JS, stop here.
1709  _ke->accept();
1710  return;
1711  }
1712 
1713  int offs = (viewport()->height() < 30) ? viewport()->height() : 30; // ### ??
1714  if (_ke->modifiers() & Qt::ShiftModifier)
1715  switch(_ke->key())
1716  {
1717  case Qt::Key_Space:
1718  verticalScrollBar()->setValue( verticalScrollBar()->value() -viewport()->height() + offs );
1719  if(d->scrollSuspended)
1720  d->newScrollTimer(this, 0);
1721  break;
1722 
1723  case Qt::Key_Down:
1724  case Qt::Key_J:
1725  d->adjustScroller(this, KHTMLViewPrivate::ScrollDown, KHTMLViewPrivate::ScrollUp);
1726  break;
1727 
1728  case Qt::Key_Up:
1729  case Qt::Key_K:
1730  d->adjustScroller(this, KHTMLViewPrivate::ScrollUp, KHTMLViewPrivate::ScrollDown);
1731  break;
1732 
1733  case Qt::Key_Left:
1734  case Qt::Key_H:
1735  d->adjustScroller(this, KHTMLViewPrivate::ScrollLeft, KHTMLViewPrivate::ScrollRight);
1736  break;
1737 
1738  case Qt::Key_Right:
1739  case Qt::Key_L:
1740  d->adjustScroller(this, KHTMLViewPrivate::ScrollRight, KHTMLViewPrivate::ScrollLeft);
1741  break;
1742  }
1743  else
1744  switch ( _ke->key() )
1745  {
1746  case Qt::Key_Down:
1747  case Qt::Key_J:
1748  if (!d->scrollTimerId || d->scrollSuspended)
1749  verticalScrollBar()->setValue( verticalScrollBar()->value()+10 );
1750  if (d->scrollTimerId)
1751  d->newScrollTimer(this, 0);
1752  break;
1753 
1754  case Qt::Key_Space:
1755  case Qt::Key_PageDown:
1756  d->shouldSmoothScroll = true;
1757  verticalScrollBar()->setValue( verticalScrollBar()->value() +viewport()->height() - offs );
1758  if(d->scrollSuspended)
1759  d->newScrollTimer(this, 0);
1760  break;
1761 
1762  case Qt::Key_Up:
1763  case Qt::Key_K:
1764  if (!d->scrollTimerId || d->scrollSuspended)
1765  verticalScrollBar()->setValue( verticalScrollBar()->value()-10 );
1766  if (d->scrollTimerId)
1767  d->newScrollTimer(this, 0);
1768  break;
1769 
1770  case Qt::Key_PageUp:
1771  d->shouldSmoothScroll = true;
1772  verticalScrollBar()->setValue( verticalScrollBar()->value() -viewport()->height() + offs );
1773  if(d->scrollSuspended)
1774  d->newScrollTimer(this, 0);
1775  break;
1776  case Qt::Key_Right:
1777  case Qt::Key_L:
1778  if (!d->scrollTimerId || d->scrollSuspended)
1779  horizontalScrollBar()->setValue( horizontalScrollBar()->value()+10 );
1780  if (d->scrollTimerId)
1781  d->newScrollTimer(this, 0);
1782  break;
1783 
1784  case Qt::Key_Left:
1785  case Qt::Key_H:
1786  if (!d->scrollTimerId || d->scrollSuspended)
1787  horizontalScrollBar()->setValue( horizontalScrollBar()->value()-10 );
1788  if (d->scrollTimerId)
1789  d->newScrollTimer(this, 0);
1790  break;
1791  case Qt::Key_Enter:
1792  case Qt::Key_Return:
1793  // ### FIXME:
1794  // or even better to HTMLAnchorElementImpl::event()
1795  if (m_part->xmlDocImpl()) {
1796  NodeImpl *n = m_part->xmlDocImpl()->focusNode();
1797  if (n)
1798  n->setActive();
1799  }
1800  break;
1801  case Qt::Key_Home:
1802  verticalScrollBar()->setValue( 0 );
1803  horizontalScrollBar()->setValue( 0 );
1804  if(d->scrollSuspended)
1805  d->newScrollTimer(this, 0);
1806  break;
1807  case Qt::Key_End:
1808  verticalScrollBar()->setValue( contentsHeight() - visibleHeight() );
1809  if(d->scrollSuspended)
1810  d->newScrollTimer(this, 0);
1811  break;
1812  case Qt::Key_Shift:
1813  // what are you doing here?
1814  _ke->ignore();
1815  return;
1816  default:
1817  if (d->scrollTimerId)
1818  d->newScrollTimer(this, 0);
1819  _ke->ignore();
1820  return;
1821  }
1822 
1823  _ke->accept();
1824 }
1825 
1826 void KHTMLView::keyReleaseEvent(QKeyEvent *_ke)
1827 {
1828  if( d->scrollSuspendPreActivate && _ke->key() != Qt::Key_Shift )
1829  d->scrollSuspendPreActivate = false;
1830  if( _ke->key() == Qt::Key_Shift && d->scrollSuspendPreActivate && !(_ke->modifiers() & Qt::ShiftModifier))
1831  if (d->scrollTimerId) {
1832  d->scrollSuspended = !d->scrollSuspended;
1833  if (d->scrollSuspended)
1834  d->stopScrolling();
1835  }
1836 
1837  if (d->accessKeysEnabled)
1838  {
1839  if (d->accessKeysPreActivate && _ke->key() != Qt::Key_Control)
1840  d->accessKeysPreActivate=false;
1841  if (d->accessKeysPreActivate && !(_ke->modifiers() & Qt::ControlModifier))
1842  {
1843  displayAccessKeys();
1844  m_part->setStatusBarText(i18n("Access Keys activated"),KHTMLPart::BarOverrideText);
1845  d->accessKeysActivated = true;
1846  d->accessKeysPreActivate = false;
1847  _ke->accept();
1848  return;
1849  }
1850  else if (d->accessKeysActivated)
1851  {
1852  accessKeysTimeout();
1853  _ke->accept();
1854  return;
1855  }
1856  }
1857 
1858  // Send keyup event
1859  if ( dispatchKeyEvent( _ke ) )
1860  {
1861  _ke->accept();
1862  return;
1863  }
1864 
1865  QScrollArea::keyReleaseEvent(_ke);
1866 }
1867 
1868 bool KHTMLView::focusNextPrevChild( bool next )
1869 {
1870  // Now try to find the next child
1871  if (m_part->xmlDocImpl() && focusNextPrevNode(next))
1872  {
1873  if (m_part->xmlDocImpl()->focusNode())
1874  kDebug() << "focusNode.name: "
1875  << m_part->xmlDocImpl()->focusNode()->nodeName().string() << endl;
1876  return true; // focus node found
1877  }
1878 
1879  // If we get here, pass tabbing control up to the next/previous child in our parent
1880  d->pseudoFocusNode = KHTMLViewPrivate::PFNone;
1881  if (m_part->parentPart() && m_part->parentPart()->view())
1882  return m_part->parentPart()->view()->focusNextPrevChild(next);
1883 
1884  return QWidget::focusNextPrevChild(next);
1885 }
1886 
1887 void KHTMLView::doAutoScroll()
1888 {
1889  QPoint pos = QCursor::pos();
1890  QPoint off;
1891  KHTMLView* v = m_kwp->isRedirected() ? m_kwp->rootViewPos(off) : this;
1892  pos = v->viewport()->mapFromGlobal( pos );
1893  pos -= off;
1894  int xm, ym;
1895  viewportToContents(pos.x(), pos.y(), xm, ym); // ###
1896 
1897  pos = QPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y());
1898  if ( (pos.y() < 0) || (pos.y() > visibleHeight()) ||
1899  (pos.x() < 0) || (pos.x() > visibleWidth()) )
1900  {
1901  ensureVisible( xm, ym, 0, 5 );
1902 
1903 #ifndef KHTML_NO_SELECTION
1904  // extend the selection while scrolling
1905  DOM::Node innerNode;
1906  if (m_part->isExtendingSelection()) {
1907  RenderObject::NodeInfo renderInfo(true/*readonly*/, false/*active*/);
1908  m_part->xmlDocImpl()->renderer()->layer()
1909  ->nodeAtPoint(renderInfo, xm, ym);
1910  innerNode = renderInfo.innerNode();
1911  }/*end if*/
1912 
1913  if (innerNode.handle() && innerNode.handle()->renderer()
1914  && innerNode.handle()->renderer()->shouldSelect()) {
1915  m_part->extendSelectionTo(xm, ym, innerNode);
1916  }/*end if*/
1917 #endif // KHTML_NO_SELECTION
1918  }
1919 }
1920 
1921 // KHTML defines its own stacking order for any object and thus takes
1922 // control of widget painting whenever it can. This is called "redirection".
1923 //
1924 // Redirected widgets are placed off screen. When they are declared as a child of our view (ChildPolished event),
1925 // an event filter is installed, so as to catch any paint event and translate them as update() of the view's main widget.
1926 //
1927 // Painting also happens spontaneously within widgets. In this case, the widget would update() parts of itself.
1928 // While this ordinarily results in a paintEvent being schedduled, it is not the case with off screen widgets.
1929 // Thus update() is monitored by using the mechanism that deffers any update call happening during a paint event,
1930 // transforming it into a posted UpdateLater event. Hence the need to set Qt::WA_WState_InPaintEvent on redirected widgets.
1931 //
1932 // Once the UpdateLater event has been received, Qt::WA_WState_InPaintEvent is removed and the process continues
1933 // with the update of the corresponding rect on the view. That in turn will make our painting subsystem render()
1934 // the widget at the correct stacking position.
1935 //
1936 // For non-redirected (e.g. external) widgets, z-order is honoured through masking. cf.RenderLayer::updateWidgetMasks
1937 
1938 static void handleWidget(QWidget* w, KHTMLView* view, bool recurse=true)
1939 {
1940  if (w->isWindow())
1941  return;
1942 
1943  if (!qobject_cast<QFrame*>(w))
1944  w->setAttribute( Qt::WA_NoSystemBackground );
1945 
1946  w->setAttribute(Qt::WA_WState_InPaintEvent);
1947 
1948  if (!(w->objectName() == "KLineEditButton"))
1949  w->setAttribute(Qt::WA_OpaquePaintEvent);
1950 
1951  w->installEventFilter(view);
1952 
1953  if (!recurse)
1954  return;
1955  if (qobject_cast<KHTMLView*>(w)) {
1956  handleWidget(static_cast<KHTMLView*>(w)->widget(), view, false);
1957  handleWidget(static_cast<KHTMLView*>(w)->horizontalScrollBar(), view, false);
1958  handleWidget(static_cast<KHTMLView*>(w)->verticalScrollBar(), view, false);
1959  return;
1960  }
1961 
1962  QObjectList children = w->children();
1963  foreach (QObject* object, children) {
1964  QWidget *widget = qobject_cast<QWidget*>(object);
1965  if (widget)
1966  handleWidget(widget, view);
1967  }
1968 }
1969 
1970 class KHTMLBackingStoreHackWidget : public QWidget
1971 {
1972 public:
1973  void publicEvent(QEvent *e)
1974  {
1975  QWidget::event(e);
1976  }
1977 };
1978 
1979 bool KHTMLView::viewportEvent ( QEvent * e )
1980 {
1981  switch (e->type()) {
1982  // those must not be dispatched to the specialized handlers
1983  // as widgetEvent() already took care of that
1984  case QEvent::MouseButtonPress:
1985  case QEvent::MouseButtonRelease:
1986  case QEvent::MouseButtonDblClick:
1987  case QEvent::MouseMove:
1988 #ifndef QT_NO_WHEELEVENT
1989  case QEvent::Wheel:
1990 #endif
1991  case QEvent::ContextMenu:
1992  case QEvent::DragEnter:
1993  case QEvent::DragMove:
1994  case QEvent::DragLeave:
1995  case QEvent::Drop:
1996  return false;
1997  default:
1998  break;
1999  }
2000  return QScrollArea::viewportEvent(e);
2001 }
2002 
2003 static void setInPaintEventFlag(QWidget* w, bool b = true, bool recurse=true)
2004 {
2005  w->setAttribute(Qt::WA_WState_InPaintEvent, b);
2006 
2007  if (!recurse)
2008  return;
2009  if (qobject_cast<KHTMLView*>(w)) {
2010  setInPaintEventFlag(static_cast<KHTMLView*>(w)->widget(), b, false);
2011  setInPaintEventFlag(static_cast<KHTMLView*>(w)->horizontalScrollBar(), b, false);
2012  setInPaintEventFlag(static_cast<KHTMLView*>(w)->verticalScrollBar(), b, false);
2013  return;
2014  }
2015 
2016  foreach(QObject* cw, w->children()) {
2017  if (cw->isWidgetType() && ! static_cast<QWidget*>(cw)->isWindow()
2018  && !(static_cast<QWidget*>(cw)->windowModality() & Qt::ApplicationModal)) {
2019  setInPaintEventFlag(static_cast<QWidget*>(cw), b);
2020  }
2021  }
2022 }
2023 
2024 bool KHTMLView::eventFilter(QObject *o, QEvent *e)
2025 {
2026  if ( e->type() == QEvent::ShortcutOverride ) {
2027  QKeyEvent* ke = (QKeyEvent*) e;
2028  if (m_part->isEditable() || m_part->isCaretMode()
2029  || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()
2030  && m_part->xmlDocImpl()->focusNode()->isContentEditable())) {
2031  if ( (ke->modifiers() & Qt::ControlModifier) || (ke->modifiers() & Qt::ShiftModifier) ) {
2032  switch ( ke->key() ) {
2033  case Qt::Key_Left:
2034  case Qt::Key_Right:
2035  case Qt::Key_Up:
2036  case Qt::Key_Down:
2037  case Qt::Key_Home:
2038  case Qt::Key_End:
2039  ke->accept();
2040  return true;
2041  default:
2042  break;
2043  }
2044  }
2045  }
2046  }
2047 
2048  if ( e->type() == QEvent::Leave ) {
2049  if ( d->cursorIconWidget )
2050  d->cursorIconWidget->hide();
2051  m_part->resetHoverText();
2052  }
2053 
2054  QWidget *view = widget();
2055  if (o == view) {
2056  if (widgetEvent(e))
2057  return true;
2058  else if (e->type() == QEvent::Resize) {
2059  updateScrollBars();
2060  return false;
2061  }
2062  } else if (o->isWidgetType()) {
2063  QWidget *v = static_cast<QWidget *>(o);
2064  QWidget *c = v;
2065  while (v && v != view) {
2066  c = v;
2067  v = v->parentWidget();
2068  }
2069  KHTMLWidget* k = dynamic_cast<KHTMLWidget*>(c);
2070  if (v && k && k->m_kwp->isRedirected()) {
2071  bool block = false;
2072  bool isUpdate = false;
2073  QWidget *w = static_cast<QWidget *>(o);
2074  switch(e->type()) {
2075  case QEvent::UpdateRequest: {
2076  // implicitly call qt_syncBackingStore(w)
2077  static_cast<KHTMLBackingStoreHackWidget *>(w)->publicEvent(e);
2078  block = true;
2079  break;
2080  }
2081  case QEvent::UpdateLater:
2082  isUpdate = true;
2083  // no break;
2084  case QEvent::Paint:
2085  if (!allowWidgetPaintEvents) {
2086  // eat the event. Like this we can control exactly when the widget
2087  // gets repainted.
2088  block = true;
2089  int x = 0, y = 0;
2090  QWidget *v = w;
2091  while (v && v->parentWidget() != view) {
2092  x += v->x();
2093  y += v->y();
2094  v = v->parentWidget();
2095  }
2096 
2097  QPoint ap = k->m_kwp->absolutePos();
2098  x += ap.x();
2099  y += ap.y();
2100 
2101  QRect pr = isUpdate ? static_cast<QUpdateLaterEvent*>(e)->region().boundingRect() : static_cast<QPaintEvent*>(e)->rect();
2102  bool asap = !d->contentsMoving && qobject_cast<QAbstractScrollArea*>(c);
2103 
2104  if (isUpdate) {
2105  setInPaintEventFlag(w, false);
2106  if (asap)
2107  w->repaint(static_cast<QUpdateLaterEvent*>(e)->region());
2108  else
2109  w->update(static_cast<QUpdateLaterEvent*>(e)->region());
2110  setInPaintEventFlag(w);
2111  }
2112 
2113  // QScrollView needs fast repaints
2114  if ( asap && !isUpdate && !d->painting && m_part->xmlDocImpl() && m_part->xmlDocImpl()->renderer() &&
2115  !static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer())->needsLayout() ) {
2116  repaintContents(x + pr.x(), y + pr.y(),
2117  pr.width(), pr.height()+1); // ### investigate that +1 (shows up when
2118  // updating e.g a textarea's blinking cursor)
2119  } else if (!d->painting) {
2120  scheduleRepaint(x + pr.x(), y + pr.y(),
2121  pr.width(), pr.height()+1, asap);
2122  }
2123  }
2124  break;
2125  case QEvent::MouseMove:
2126  case QEvent::MouseButtonPress:
2127  case QEvent::MouseButtonRelease:
2128  case QEvent::MouseButtonDblClick: {
2129 
2130  if (0 && w->parentWidget() == view && !qobject_cast<QScrollBar*>(w) && !::qobject_cast<QScrollBar *>(w)) {
2131  QMouseEvent *me = static_cast<QMouseEvent *>(e);
2132  QPoint pt = w->mapTo( view, me->pos());
2133  QMouseEvent me2(me->type(), pt, me->button(), me->buttons(), me->modifiers());
2134 
2135  if (e->type() == QEvent::MouseMove)
2136  mouseMoveEvent(&me2);
2137  else if(e->type() == QEvent::MouseButtonPress)
2138  mousePressEvent(&me2);
2139  else if(e->type() == QEvent::MouseButtonRelease)
2140  mouseReleaseEvent(&me2);
2141  else
2142  mouseDoubleClickEvent(&me2);
2143  block = true;
2144  }
2145  break;
2146  }
2147  case QEvent::KeyPress:
2148  case QEvent::KeyRelease:
2149  if (w->parentWidget() == view && !qobject_cast<QScrollBar*>(w)) {
2150  QKeyEvent *ke = static_cast<QKeyEvent *>(e);
2151  if (e->type() == QEvent::KeyPress) {
2152  keyPressEvent(ke);
2153  ke->accept();
2154  } else{
2155  keyReleaseEvent(ke);
2156  ke->accept();
2157  }
2158  block = true;
2159  }
2160 
2161  if (qobject_cast<KUrlRequester*>(w->parentWidget()) &&
2162  e->type() == QEvent::KeyPress) {
2163  // Since keypress events on the upload widget will
2164  // be forwarded to the lineedit anyway,
2165  // block the original copy at this level to prevent
2166  // double-emissions of events it doesn't accept
2167  e->ignore();
2168  block = true;
2169  }
2170 
2171  break;
2172  case QEvent::FocusIn:
2173  case QEvent::FocusOut: {
2174  QPoint dummy;
2175  KHTMLView* root = m_kwp->rootViewPos(dummy);
2176  if (!root)
2177  root = this;
2178  block = static_cast<QFocusEvent*>(e)->reason() != Qt::MouseFocusReason || root->underMouse();
2179  break;
2180  }
2181  default:
2182  break;
2183  }
2184  if (block) {
2185  //qDebug("eating event");
2186  return true;
2187  }
2188  }
2189  }
2190 
2191 // kDebug(6000) <<"passing event on to sv event filter object=" << o->className() << " event=" << e->type();
2192  return QScrollArea::eventFilter(o, e);
2193 }
2194 
2195 bool KHTMLView::widgetEvent(QEvent* e)
2196 {
2197  switch (e->type()) {
2198  case QEvent::MouseButtonPress:
2199  case QEvent::MouseButtonRelease:
2200  case QEvent::MouseButtonDblClick:
2201  case QEvent::MouseMove:
2202  case QEvent::Paint:
2203 #ifndef QT_NO_WHEELEVENT
2204  case QEvent::Wheel:
2205 #endif
2206  case QEvent::ContextMenu:
2207  case QEvent::DragEnter:
2208  case QEvent::DragMove:
2209  case QEvent::DragLeave:
2210  case QEvent::Drop:
2211  return QFrame::event(e);
2212  case QEvent::ChildPolished: {
2213  // we need to install an event filter on all children of the widget() to
2214  // be able to get correct stacking of children within the document.
2215  QObject *c = static_cast<QChildEvent *>(e)->child();
2216  if (c->isWidgetType()) {
2217  QWidget *w = static_cast<QWidget *>(c);
2218  // don't install the event filter on toplevels
2219  if (!(w->windowFlags() & Qt::Window) && !(w->windowModality() & Qt::ApplicationModal)) {
2220  KHTMLWidget* k = dynamic_cast<KHTMLWidget*>(w);
2221  if (k && k->m_kwp->isRedirected()) {
2222  w->unsetCursor();
2223  handleWidget(w, this);
2224  }
2225  }
2226  }
2227  break;
2228  }
2229  case QEvent::Move: {
2230  if (static_cast<QMoveEvent*>(e)->pos() != QPoint(0,0)) {
2231  widget()->move(0,0);
2232  updateScrollBars();
2233  return true;
2234  }
2235  break;
2236  }
2237  default:
2238  break;
2239  }
2240  return false;
2241 }
2242 
2243 bool KHTMLView::hasLayoutPending()
2244 {
2245  return d->layoutTimerId && !d->firstLayoutPending;
2246 }
2247 
2248 DOM::NodeImpl *KHTMLView::nodeUnderMouse() const
2249 {
2250  return d->underMouse;
2251 }
2252 
2253 DOM::NodeImpl *KHTMLView::nonSharedNodeUnderMouse() const
2254 {
2255  return d->underMouseNonShared;
2256 }
2257 
2258 bool KHTMLView::scrollTo(const QRect &bounds)
2259 {
2260  d->scrollingSelf = true; // so scroll events get ignored
2261 
2262  int x, y, xe, ye;
2263  x = bounds.left();
2264  y = bounds.top();
2265  xe = bounds.right();
2266  ye = bounds.bottom();
2267 
2268  //kDebug(6000)<<"scrolling coords: x="<<x<<" y="<<y<<" width="<<xe-x<<" height="<<ye-y;
2269 
2270  int deltax;
2271  int deltay;
2272 
2273  int curHeight = visibleHeight();
2274  int curWidth = visibleWidth();
2275 
2276  if (ye-y>curHeight-d->borderY)
2277  ye = y + curHeight - d->borderY;
2278 
2279  if (xe-x>curWidth-d->borderX)
2280  xe = x + curWidth - d->borderX;
2281 
2282  // is xpos of target left of the view's border?
2283  if (x < contentsX() + d->borderX )
2284  deltax = x - contentsX() - d->borderX;
2285  // is xpos of target right of the view's right border?
2286  else if (xe + d->borderX > contentsX() + curWidth)
2287  deltax = xe + d->borderX - ( contentsX() + curWidth );
2288  else
2289  deltax = 0;
2290 
2291  // is ypos of target above upper border?
2292  if (y < contentsY() + d->borderY)
2293  deltay = y - contentsY() - d->borderY;
2294  // is ypos of target below lower border?
2295  else if (ye + d->borderY > contentsY() + curHeight)
2296  deltay = ye + d->borderY - ( contentsY() + curHeight );
2297  else
2298  deltay = 0;
2299 
2300  int maxx = curWidth-d->borderX;
2301  int maxy = curHeight-d->borderY;
2302 
2303  int scrollX, scrollY;
2304 
2305  scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax>-maxx ? deltax : -maxx);
2306  scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay>-maxy ? deltay : -maxy);
2307 
2308  if (contentsX() + scrollX < 0)
2309  scrollX = -contentsX();
2310  else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
2311  scrollX = contentsWidth() - visibleWidth() - contentsX();
2312 
2313  if (contentsY() + scrollY < 0)
2314  scrollY = -contentsY();
2315  else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
2316  scrollY = contentsHeight() - visibleHeight() - contentsY();
2317 
2318  horizontalScrollBar()->setValue( horizontalScrollBar()->value()+scrollX );
2319  verticalScrollBar()->setValue( verticalScrollBar()->value()+scrollY );
2320 
2321  d->scrollingSelf = false;
2322 
2323  if ( (abs(deltax)<=maxx) && (abs(deltay)<=maxy) )
2324  return true;
2325  else return false;
2326 
2327 }
2328 
2329 bool KHTMLView::focusNextPrevNode(bool next)
2330 {
2331  // Sets the focus node of the document to be the node after (or if
2332  // next is false, before) the current focus node. Only nodes that
2333  // are selectable (i.e. for which isFocusable() returns true) are
2334  // taken into account, and the order used is that specified in the
2335  // HTML spec (see DocumentImpl::nextFocusNode() and
2336  // DocumentImpl::previousFocusNode() for details).
2337 
2338  DocumentImpl *doc = m_part->xmlDocImpl();
2339  NodeImpl *oldFocusNode = doc->focusNode();
2340 
2341  // See whether we're in the middle of a detach, or hiding of the
2342  // widget. In this case, we will just clear focus, being careful not to emit events
2343  // or update rendering. Doing this also prevents the code below from going bonkers with
2344  // oldFocusNode not actually being focusable, etc.
2345  if (oldFocusNode) {
2346  if ((oldFocusNode->renderer() && !oldFocusNode->renderer()->parent())
2347  || !oldFocusNode->isTabFocusable()) {
2348  doc->quietResetFocus();
2349  return true;
2350  }
2351  }
2352 
2353 #if 1
2354  // If the user has scrolled the document, then instead of picking
2355  // the next focusable node in the document, use the first one that
2356  // is within the visible area (if possible).
2357  if (d->scrollBarMoved)
2358  {
2359  NodeImpl *toFocus;
2360  if (next)
2361  toFocus = doc->nextFocusNode(oldFocusNode);
2362  else
2363  toFocus = doc->previousFocusNode(oldFocusNode);
2364 
2365  if (!toFocus && oldFocusNode) {
2366  if (next)
2367  toFocus = doc->nextFocusNode(NULL);
2368  else
2369  toFocus = doc->previousFocusNode(NULL);
2370  }
2371 
2372  while (toFocus && toFocus != oldFocusNode)
2373  {
2374 
2375  QRect focusNodeRect = toFocus->getRect();
2376  if ((focusNodeRect.left() > contentsX()) && (focusNodeRect.right() < contentsX() + visibleWidth()) &&
2377  (focusNodeRect.top() > contentsY()) && (focusNodeRect.bottom() < contentsY() + visibleHeight())) {
2378  {
2379  QRect r = toFocus->getRect();
2380  ensureVisible( r.right(), r.bottom());
2381  ensureVisible( r.left(), r.top());
2382  d->scrollBarMoved = false;
2383  d->tabMovePending = false;
2384  d->lastTabbingDirection = next;
2385  d->pseudoFocusNode = KHTMLViewPrivate::PFNone;
2386  m_part->xmlDocImpl()->setFocusNode(toFocus);
2387  Node guard(toFocus);
2388  if (!toFocus->hasOneRef() )
2389  {
2390  emit m_part->nodeActivated(Node(toFocus));
2391  }
2392  return true;
2393  }
2394  }
2395  if (next)
2396  toFocus = doc->nextFocusNode(toFocus);
2397  else
2398  toFocus = doc->previousFocusNode(toFocus);
2399 
2400  if (!toFocus && oldFocusNode)
2401  {
2402  if (next)
2403  {
2404  toFocus = doc->nextFocusNode(NULL);
2405  }
2406  else
2407  {
2408  toFocus = doc->previousFocusNode(NULL);
2409  }
2410  }
2411  }
2412 
2413  d->scrollBarMoved = false;
2414  }
2415 #endif
2416 
2417  if (!oldFocusNode && d->pseudoFocusNode == KHTMLViewPrivate::PFNone)
2418  {
2419  ensureVisible(contentsX(), next?0:contentsHeight());
2420  d->scrollBarMoved = false;
2421  d->pseudoFocusNode = next?KHTMLViewPrivate::PFTop:KHTMLViewPrivate::PFBottom;
2422  return true;
2423  }
2424 
2425  NodeImpl *newFocusNode = NULL;
2426 
2427  if (d->tabMovePending && next != d->lastTabbingDirection)
2428  {
2429  //kDebug ( 6000 ) << " tab move pending and tabbing direction changed!\n";
2430  newFocusNode = oldFocusNode;
2431  }
2432  else if (next)
2433  {
2434  if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFTop )
2435  newFocusNode = doc->nextFocusNode(oldFocusNode);
2436  }
2437  else
2438  {
2439  if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFBottom )
2440  newFocusNode = doc->previousFocusNode(oldFocusNode);
2441  }
2442 
2443  bool targetVisible = false;
2444  if (!newFocusNode)
2445  {
2446  if ( next )
2447  {
2448  targetVisible = scrollTo(QRect(contentsX()+visibleWidth()/2,contentsHeight()-d->borderY,0,0));
2449  }
2450  else
2451  {
2452  targetVisible = scrollTo(QRect(contentsX()+visibleWidth()/2,d->borderY,0,0));
2453  }
2454  }
2455  else
2456  {
2457  // if it's an editable element, activate the caret
2458  if (!m_part->isCaretMode() && newFocusNode->isContentEditable()) {
2459  kDebug(6200) << "show caret! fn: " << newFocusNode->nodeName().string() << endl;
2460  m_part->clearCaretRectIfNeeded();
2461  m_part->d->editor_context.m_selection.moveTo(Position(newFocusNode, 0L));
2462  m_part->setCaretVisible(true);
2463  } else {
2464  m_part->setCaretVisible(false);
2465  kDebug(6200) << "hide caret! fn: " << newFocusNode->nodeName().string() << endl;
2466  }
2467  m_part->notifySelectionChanged();
2468 
2469  targetVisible = scrollTo(newFocusNode->getRect());
2470  }
2471 
2472  if (targetVisible)
2473  {
2474  //kDebug ( 6000 ) << " target reached.\n";
2475  d->tabMovePending = false;
2476 
2477  m_part->xmlDocImpl()->setFocusNode(newFocusNode);
2478  if (newFocusNode)
2479  {
2480  Node guard(newFocusNode);
2481  if (!newFocusNode->hasOneRef() )
2482  {
2483  emit m_part->nodeActivated(Node(newFocusNode));
2484  }
2485  return true;
2486  }
2487  else
2488  {
2489  d->pseudoFocusNode = next?KHTMLViewPrivate::PFBottom:KHTMLViewPrivate::PFTop;
2490  return false;
2491  }
2492  }
2493  else
2494  {
2495  if (!d->tabMovePending)
2496  d->lastTabbingDirection = next;
2497  d->tabMovePending = true;
2498  return true;
2499  }
2500 }
2501 
2502 void KHTMLView::displayAccessKeys()
2503 {
2504  QVector< QChar > taken;
2505  displayAccessKeys( NULL, this, taken, false );
2506  displayAccessKeys( NULL, this, taken, true );
2507 }
2508 
2509 void KHTMLView::displayAccessKeys( KHTMLView* caller, KHTMLView* origview, QVector< QChar >& taken, bool use_fallbacks )
2510 {
2511  QMap< ElementImpl*, QChar > fallbacks;
2512  if( use_fallbacks )
2513  fallbacks = buildFallbackAccessKeys();
2514  for( NodeImpl* n = m_part->xmlDocImpl(); n != NULL; n = n->traverseNextNode()) {
2515  if( n->isElementNode()) {
2516  ElementImpl* en = static_cast< ElementImpl* >( n );
2517  DOMString s = en->getAttribute( ATTR_ACCESSKEY );
2518  QString accesskey;
2519  if( s.length() == 1 ) {
2520  QChar a = s.string()[ 0 ].toUpper();
2521  if( qFind( taken.begin(), taken.end(), a ) == taken.end()) // !contains
2522  accesskey = a;
2523  }
2524  if( accesskey.isNull() && fallbacks.contains( en )) {
2525  QChar a = fallbacks[ en ].toUpper();
2526  if( qFind( taken.begin(), taken.end(), a ) == taken.end()) // !contains
2527  accesskey = QString( "<qt><i>" ) + a + "</i></qt>";
2528  }
2529  if( !accesskey.isNull()) {
2530  QRect rec=en->getRect();
2531  QLabel *lab=new QLabel(accesskey,widget());
2532  lab->setAttribute(Qt::WA_DeleteOnClose);
2533  lab->setObjectName("KHTMLAccessKey");
2534  connect( origview, SIGNAL(hideAccessKeys()), lab, SLOT(close()) );
2535  connect( this, SIGNAL(repaintAccessKeys()), lab, SLOT(repaint()));
2536  lab->setPalette(QToolTip::palette());
2537  lab->setLineWidth(2);
2538  lab->setFrameStyle(QFrame::Box | QFrame::Plain);
2539  lab->setMargin(3);
2540  lab->adjustSize();
2541  lab->setParent( widget() );
2542  lab->setAutoFillBackground(true);
2543  lab->move(
2544  qMin(rec.left()+rec.width()/2 - contentsX(), contentsWidth() - lab->width()),
2545  qMin(rec.top()+rec.height()/2 - contentsY(), contentsHeight() - lab->height()));
2546  lab->show();
2547  taken.append( accesskey[ 0 ] );
2548  }
2549  }
2550  }
2551  if( use_fallbacks )
2552  return;
2553 
2554  QList<KParts::ReadOnlyPart*> frames = m_part->frames();
2555  foreach( KParts::ReadOnlyPart* cur, frames ) {
2556  if( !qobject_cast<KHTMLPart*>(cur) )
2557  continue;
2558  KHTMLPart* part = static_cast< KHTMLPart* >( cur );
2559  if( part->view() && part->view() != caller )
2560  part->view()->displayAccessKeys( this, origview, taken, use_fallbacks );
2561  }
2562 
2563  // pass up to the parent
2564  if (m_part->parentPart() && m_part->parentPart()->view()
2565  && m_part->parentPart()->view() != caller)
2566  m_part->parentPart()->view()->displayAccessKeys( this, origview, taken, use_fallbacks );
2567 }
2568 
2569 bool KHTMLView::isScrollingFromMouseWheel() const
2570 {
2571  return d->scrollingFromWheel != QPoint(-1,-1);
2572 }
2573 
2574 void KHTMLView::accessKeysTimeout()
2575 {
2576  d->accessKeysActivated=false;
2577  d->accessKeysPreActivate = false;
2578  m_part->setStatusBarText(QString(), KHTMLPart::BarOverrideText);
2579  emit hideAccessKeys();
2580 }
2581 
2582 // Handling of the HTML accesskey attribute.
2583 bool KHTMLView::handleAccessKey( const QKeyEvent* ev )
2584 {
2585 // Qt interprets the keyevent also with the modifiers, and ev->text() matches that,
2586 // but this code must act as if the modifiers weren't pressed
2587  QChar c;
2588  if( ev->key() >= Qt::Key_A && ev->key() <= Qt::Key_Z )
2589  c = 'A' + ev->key() - Qt::Key_A;
2590  else if( ev->key() >= Qt::Key_0 && ev->key() <= Qt::Key_9 )
2591  c = '0' + ev->key() - Qt::Key_0;
2592  else {
2593  // TODO fake XKeyEvent and XLookupString ?
2594  // This below seems to work e.g. for eacute though.
2595  if( ev->text().length() == 1 )
2596  c = ev->text()[ 0 ];
2597  }
2598  if( c.isNull())
2599  return false;
2600  return focusNodeWithAccessKey( c );
2601 }
2602 
2603 bool KHTMLView::focusNodeWithAccessKey( QChar c, KHTMLView* caller )
2604 {
2605  DocumentImpl *doc = m_part->xmlDocImpl();
2606  if( !doc )
2607  return false;
2608  ElementImpl* node = doc->findAccessKeyElement( c );
2609  if( !node ) {
2610  QList<KParts::ReadOnlyPart*> frames = m_part->frames();
2611  foreach( KParts::ReadOnlyPart* cur, frames ) {
2612  if( !qobject_cast<KHTMLPart*>(cur) )
2613  continue;
2614  KHTMLPart* part = static_cast< KHTMLPart* >( cur );
2615  if( part->view() && part->view() != caller
2616  && part->view()->focusNodeWithAccessKey( c, this ))
2617  return true;
2618  }
2619  // pass up to the parent
2620  if (m_part->parentPart() && m_part->parentPart()->view()
2621  && m_part->parentPart()->view() != caller
2622  && m_part->parentPart()->view()->focusNodeWithAccessKey( c, this ))
2623  return true;
2624  if( caller == NULL ) { // the active frame (where the accesskey was pressed)
2625  const QMap< ElementImpl*, QChar > fallbacks = buildFallbackAccessKeys();
2626  for( QMap< ElementImpl*, QChar >::ConstIterator it = fallbacks.begin();
2627  it != fallbacks.end();
2628  ++it )
2629  if( *it == c ) {
2630  node = it.key();
2631  break;
2632  }
2633  }
2634  if( node == NULL )
2635  return false;
2636  }
2637 
2638  // Scroll the view as necessary to ensure that the new focus node is visible
2639 
2640  QRect r = node->getRect();
2641  ensureVisible( r.right(), r.bottom());
2642  ensureVisible( r.left(), r.top());
2643 
2644  Node guard( node );
2645  if( node->isFocusable()) {
2646  if (node->id()==ID_LABEL) {
2647  // if Accesskey is a label, give focus to the label's referrer.
2648  node=static_cast<ElementImpl *>(static_cast< HTMLLabelElementImpl* >( node )->getFormElement());
2649  if (!node) return true;
2650  guard = node;
2651  }
2652  // Set focus node on the document
2653  m_part->xmlDocImpl()->setFocusNode(node);
2654 
2655  if( node != NULL && node->hasOneRef()) // deleted, only held by guard
2656  return true;
2657  emit m_part->nodeActivated(Node(node));
2658  if( node != NULL && node->hasOneRef())
2659  return true;
2660  }
2661 
2662  switch( node->id()) {
2663  case ID_A:
2664  static_cast< HTMLAnchorElementImpl* >( node )->click();
2665  break;
2666  case ID_INPUT:
2667  static_cast< HTMLInputElementImpl* >( node )->click();
2668  break;
2669  case ID_BUTTON:
2670  static_cast< HTMLButtonElementImpl* >( node )->click();
2671  break;
2672  case ID_AREA:
2673  static_cast< HTMLAreaElementImpl* >( node )->click();
2674  break;
2675  case ID_TEXTAREA:
2676  break; // just focusing it is enough
2677  case ID_LEGEND:
2678  // TODO
2679  break;
2680  }
2681  return true;
2682 }
2683 
2684 static QString getElementText( NodeImpl* start, bool after )
2685 {
2686  QString ret; // nextSibling(), to go after e.g. </select>
2687  for( NodeImpl* n = after ? start->nextSibling() : start->traversePreviousNode();
2688  n != NULL;
2689  n = after ? n->traverseNextNode() : n->traversePreviousNode()) {
2690  if( n->isTextNode()) {
2691  if( after )
2692  ret += static_cast< TextImpl* >( n )->toString().string();
2693  else
2694  ret.prepend( static_cast< TextImpl* >( n )->toString().string());
2695  } else {
2696  switch( n->id()) {
2697  case ID_A:
2698  case ID_FONT:
2699  case ID_TT:
2700  case ID_U:
2701  case ID_B:
2702  case ID_I:
2703  case ID_S:
2704  case ID_STRIKE:
2705  case ID_BIG:
2706  case ID_SMALL:
2707  case ID_EM:
2708  case ID_STRONG:
2709  case ID_DFN:
2710  case ID_CODE:
2711  case ID_SAMP:
2712  case ID_KBD:
2713  case ID_VAR:
2714  case ID_CITE:
2715  case ID_ABBR:
2716  case ID_ACRONYM:
2717  case ID_SUB:
2718  case ID_SUP:
2719  case ID_SPAN:
2720  case ID_NOBR:
2721  case ID_WBR:
2722  break;
2723  case ID_TD:
2724  if( ret.trimmed().isEmpty())
2725  break;
2726  // fall through
2727  default:
2728  return ret.simplified();
2729  }
2730  }
2731  }
2732  return ret.simplified();
2733 }
2734 
2735 static QMap< NodeImpl*, QString > buildLabels( NodeImpl* start )
2736 {
2737  QMap< NodeImpl*, QString > ret;
2738  for( NodeImpl* n = start;
2739  n != NULL;
2740  n = n->traverseNextNode()) {
2741  if( n->id() == ID_LABEL ) {
2742  HTMLLabelElementImpl* label = static_cast< HTMLLabelElementImpl* >( n );
2743  NodeImpl* labelfor = label->getFormElement();
2744  if( labelfor )
2745  ret[ labelfor ] = label->innerText().string().simplified();
2746  }
2747  }
2748  return ret;
2749 }
2750 
2751 namespace khtml {
2752 struct AccessKeyData {
2753  ElementImpl* element;
2754  QString text;
2755  QString url;
2756  int priority; // 10(highest) - 0(lowest)
2757 };
2758 }
2759 
2760 QMap< ElementImpl*, QChar > KHTMLView::buildFallbackAccessKeys() const
2761 {
2762  // build a list of all possible candidate elements that could use an accesskey
2763  QLinkedList< AccessKeyData > data; // Note: this has to be a list type that keep iterators valid
2764  // when other entries are removed
2765  QMap< NodeImpl*, QString > labels = buildLabels( m_part->xmlDocImpl());
2766  QMap< QString, QChar > hrefs;
2767 
2768  for( NodeImpl* n = m_part->xmlDocImpl();
2769  n != NULL;
2770  n = n->traverseNextNode()) {
2771  if( n->isElementNode()) {
2772  ElementImpl* element = static_cast< ElementImpl* >( n );
2773  if( element->renderer() == NULL )
2774  continue; // not visible
2775  QString text;
2776  QString url;
2777  int priority = 0;
2778  bool ignore = false;
2779  bool text_after = false;
2780  bool text_before = false;
2781  switch( element->id()) {
2782  case ID_A:
2783  url = element->getAttribute(ATTR_HREF).parsedUrl().string();
2784  if( url.isEmpty()) // doesn't have href, it's only an anchor
2785  continue;
2786  text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplified();
2787  priority = 2;
2788  break;
2789  case ID_INPUT: {
2790  HTMLInputElementImpl* in = static_cast< HTMLInputElementImpl* >( element );
2791  switch( in->inputType()) {
2792  case HTMLInputElementImpl::SUBMIT:
2793  text = in->value().string();
2794  if( text.isEmpty())
2795  text = i18n( "Submit" );
2796  priority = 7;
2797  break;
2798  case HTMLInputElementImpl::IMAGE:
2799  text = in->altText().string();
2800  priority = 7;
2801  break;
2802  case HTMLInputElementImpl::BUTTON:
2803  text = in->value().string();
2804  priority = 5;
2805  break;
2806  case HTMLInputElementImpl::RESET:
2807  text = in->value().string();
2808  if( text.isEmpty())
2809  text = i18n( "Reset" );
2810  priority = 5;
2811  break;
2812  case HTMLInputElementImpl::HIDDEN:
2813  ignore = true;
2814  break;
2815  case HTMLInputElementImpl::CHECKBOX:
2816  case HTMLInputElementImpl::RADIO:
2817  text_after = true;
2818  priority = 5;
2819  break;
2820  case HTMLInputElementImpl::TEXT:
2821  case HTMLInputElementImpl::PASSWORD:
2822  case HTMLInputElementImpl::FILE:
2823  text_before = true;
2824  priority = 5;
2825  break;
2826  default:
2827  priority = 5;
2828  break;
2829  }
2830  break;
2831  }
2832  case ID_BUTTON:
2833  text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplified();
2834  switch( static_cast< HTMLButtonElementImpl* >( element )->buttonType()) {
2835  case HTMLButtonElementImpl::SUBMIT:
2836  if( text.isEmpty())
2837  text = i18n( "Submit" );
2838  priority = 7;
2839  break;
2840  case HTMLButtonElementImpl::RESET:
2841  if( text.isEmpty())
2842  text = i18n( "Reset" );
2843  priority = 5;
2844  break;
2845  default:
2846  priority = 5;
2847  break;
2848  }
2849  break;
2850  case ID_SELECT: // these don't have accesskey attribute, but quick access may be handy
2851  text_before = true;
2852  text_after = true;
2853  priority = 5;
2854  break;
2855  case ID_FRAME:
2856  ignore = true;
2857  break;
2858  default:
2859  ignore = !element->isFocusable();
2860  priority = 2;
2861  break;
2862  }
2863  if( ignore )
2864  continue;
2865 
2866  // build map of manually assigned accesskeys and their targets
2867  DOMString akey = element->getAttribute( ATTR_ACCESSKEY );
2868  if( akey.length() == 1 ) {
2869  hrefs[url] = akey.string()[ 0 ].toUpper();
2870  continue; // has accesskey set, ignore
2871  }
2872  if( text.isNull() && labels.contains( element ))
2873  text = labels[ element ];
2874  if( text.isNull() && text_before )
2875  text = getElementText( element, false );
2876  if( text.isNull() && text_after )
2877  text = getElementText( element, true );
2878  text = text.trimmed();
2879  // increase priority of items which have explicitly specified accesskeys in the config
2880  const QList< QPair< QString, QChar > > priorities
2881  = m_part->settings()->fallbackAccessKeysAssignments();
2882  for( QList< QPair< QString, QChar > >::ConstIterator it = priorities.begin();
2883  it != priorities.end();
2884  ++it ) {
2885  if( text == (*it).first )
2886  priority = 10;
2887  }
2888  AccessKeyData tmp = { element, text, url, priority };
2889  data.append( tmp );
2890  }
2891  }
2892 
2893  QList< QChar > keys;
2894  for( char c = 'A'; c <= 'Z'; ++c )
2895  keys << c;
2896  for( char c = '0'; c <= '9'; ++c )
2897  keys << c;
2898  for( NodeImpl* n = m_part->xmlDocImpl();
2899  n != NULL;
2900  n = n->traverseNextNode()) {
2901  if( n->isElementNode()) {
2902  ElementImpl* en = static_cast< ElementImpl* >( n );
2903  DOMString s = en->getAttribute( ATTR_ACCESSKEY );
2904  if( s.length() == 1 ) {
2905  QChar c = s.string()[ 0 ].toUpper();
2906  keys.removeAll( c ); // remove manually assigned accesskeys
2907  }
2908  }
2909  }
2910 
2911  QMap< ElementImpl*, QChar > ret;
2912  for( int priority = 10; priority >= 0; --priority ) {
2913  for( QLinkedList< AccessKeyData >::Iterator it = data.begin();
2914  it != data.end();
2915  ) {
2916  if( (*it).priority != priority ) {
2917  ++it;
2918  continue;
2919  }
2920  if( keys.isEmpty())
2921  break;
2922  QString text = (*it).text;
2923  QChar key;
2924  const QString url = (*it).url;
2925  // an identical link already has an accesskey assigned
2926  if( hrefs.contains( url ) ) {
2927  it = data.erase( it );
2928  continue;
2929  }
2930  if( !text.isEmpty()) {
2931  const QList< QPair< QString, QChar > > priorities
2932  = m_part->settings()->fallbackAccessKeysAssignments();
2933  for( QList< QPair< QString, QChar > >::ConstIterator it = priorities.begin();
2934  it != priorities.end();
2935  ++it )
2936  if( text == (*it).first && keys.contains( (*it).second )) {
2937  key = (*it).second;
2938  break;
2939  }
2940  }
2941  // try first to select the first character as the accesskey,
2942  // then first character of the following words,
2943  // and then simply the first free character
2944  if( key.isNull() && !text.isEmpty()) {
2945  const QStringList words = text.split( ' ' );
2946  for( QStringList::ConstIterator it = words.begin();
2947  it != words.end();
2948  ++it ) {
2949  if( keys.contains( (*it)[ 0 ].toUpper())) {
2950  key = (*it)[ 0 ].toUpper();
2951  break;
2952  }
2953  }
2954  }
2955  if( key.isNull() && !text.isEmpty()) {
2956  for( int i = 0; i < text.length(); ++i ) {
2957  if( keys.contains( text[ i ].toUpper())) {
2958  key = text[ i ].toUpper();
2959  break;
2960  }
2961  }
2962  }
2963  if( key.isNull())
2964  key = keys.front();
2965  ret[ (*it).element ] = key;
2966  keys.removeAll( key );
2967  it = data.erase( it );
2968  // assign the same accesskey also to other elements pointing to the same url
2969  if( !url.isEmpty() && !url.startsWith( "javascript:", Qt::CaseInsensitive )) {
2970  for( QLinkedList< AccessKeyData >::Iterator it2 = data.begin();
2971  it2 != data.end();
2972  ) {
2973  if( (*it2).url == url ) {
2974  ret[ (*it2).element ] = key;
2975  if( it == it2 )
2976  ++it;
2977  it2 = data.erase( it2 );
2978  } else
2979  ++it2;
2980  }
2981  }
2982  }
2983  }
2984  return ret;
2985 }
2986 
2987 void KHTMLView::setMediaType( const QString &medium )
2988 {
2989  m_medium = medium;
2990 }
2991 
2992 QString KHTMLView::mediaType() const
2993 {
2994  return m_medium;
2995 }
2996 
2997 bool KHTMLView::pagedMode() const
2998 {
2999  return d->paged;
3000 }
3001 
3002 void KHTMLView::setWidgetVisible(RenderWidget* w, bool vis)
3003 {
3004  if (vis) {
3005  d->visibleWidgets.insert(w, w->widget());
3006  }
3007  else
3008  d->visibleWidgets.remove(w);
3009 }
3010 
3011 bool KHTMLView::needsFullRepaint() const
3012 {
3013  return d->needsFullRepaint;
3014 }
3015 
3016 namespace {
3017  class QPointerDeleter
3018  {
3019  public:
3020  explicit QPointerDeleter(QObject* o) : obj(o) {}
3021  ~QPointerDeleter() { delete obj; }
3022  private:
3023  const QPointer<QObject> obj;
3024  };
3025 }
3026 
3027 void KHTMLView::print(bool quick)
3028 {
3029  if(!m_part->xmlDocImpl()) return;
3030  khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
3031  if(!root) return;
3032 
3033  QPointer<KHTMLPrintSettings> printSettings(new KHTMLPrintSettings); //XXX: doesn't save settings between prints like this
3034  const QPointerDeleter settingsDeleter(printSettings); //the printdialog takes ownership of the settings widget, thus this workaround to avoid double deletion
3035  QPrinter printer;
3036  QPointer<QPrintDialog> dialog = KdePrint::createPrintDialog(&printer, KdePrint::SystemSelectsPages, QList<QWidget*>() << printSettings.data(), this);
3037 
3038  const QPointerDeleter dialogDeleter(dialog);
3039 
3040  QString docname = m_part->xmlDocImpl()->URL().prettyUrl();
3041  if ( !docname.isEmpty() )
3042  docname = KStringHandler::csqueeze(docname, 80);
3043 
3044  if(quick || (dialog->exec() && dialog)) { /*'this' and thus dialog might have been deleted while exec()!*/
3045  viewport()->setCursor( Qt::WaitCursor ); // only viewport(), no QApplication::, otherwise we get the busy cursor in kdeprint's dialogs
3046  // set up KPrinter
3047  printer.setFullPage(false);
3048  printer.setCreator(QString("KDE %1.%2.%3 HTML Library").arg(KDE_VERSION_MAJOR).arg(KDE_VERSION_MINOR).arg(KDE_VERSION_RELEASE));
3049  printer.setDocName(docname);
3050 
3051  QPainter *p = new QPainter;
3052  p->begin( &printer );
3053  khtml::setPrintPainter( p );
3054 
3055  m_part->xmlDocImpl()->setPaintDevice( &printer );
3056  QString oldMediaType = mediaType();
3057  setMediaType( "print" );
3058  // We ignore margin settings for html and body when printing
3059  // and use the default margins from the print-system
3060  // (In Qt 3.0.x the default margins are hardcoded in Qt)
3061  m_part->xmlDocImpl()->setPrintStyleSheet( printSettings->printFriendly() ?
3062  "* { background-image: none !important;"
3063  " background-color: white !important;"
3064  " color: black !important; }"
3065  "body { margin: 0px !important; }"
3066  "html { margin: 0px !important; }" :
3067  "body { margin: 0px !important; }"
3068  "html { margin: 0px !important; }"
3069  );
3070 
3071  kDebug(6000) << "printing: physical page width = " << printer.width()
3072  << " height = " << printer.height() << endl;
3073  root->setStaticMode(true);
3074  root->setPagedMode(true);
3075  root->setWidth(printer.width());
3076 // root->setHeight(printer.height());
3077  root->setPageTop(0);
3078  root->setPageBottom(0);
3079  d->paged = true;
3080 
3081  m_part->xmlDocImpl()->styleSelector()->computeFontSizes(printer.logicalDpiY(), 100);
3082  m_part->xmlDocImpl()->updateStyleSelector();
3083  root->setPrintImages(printSettings->printImages());
3084  root->makePageBreakAvoidBlocks();
3085 
3086  root->setNeedsLayoutAndMinMaxRecalc();
3087  root->layout();
3088 
3089  // check sizes ask for action.. (scale or clip)
3090 
3091  bool printHeader = printSettings->printHeader();
3092 
3093  int headerHeight = 0;
3094  QFont headerFont("Sans Serif", 8);
3095 
3096  QString headerLeft = KGlobal::locale()->formatDate(QDate::currentDate(),KLocale::ShortDate);
3097  QString headerMid = docname;
3098  QString headerRight;
3099 
3100  if (printHeader)
3101  {
3102  p->setFont(headerFont);
3103  headerHeight = (p->fontMetrics().lineSpacing() * 3) / 2;
3104  }
3105 
3106  // ok. now print the pages.
3107  kDebug(6000) << "printing: html page width = " << root->docWidth()
3108  << " height = " << root->docHeight() << endl;
3109  kDebug(6000) << "printing: margins left = " << printer.pageRect().left() - printer.paperRect().left()
3110  << " top = " << printer.pageRect().top() - printer.paperRect().top() << endl;
3111  kDebug(6000) << "printing: paper width = " << printer.width()
3112  << " height = " << printer.height() << endl;
3113  // if the width is too large to fit on the paper we just scale
3114  // the whole thing.
3115  int pageWidth = printer.width();
3116  int pageHeight = printer.height();
3117  p->setClipRect(0,0, pageWidth, pageHeight);
3118 
3119  pageHeight -= headerHeight;
3120 
3121 #ifndef QT_NO_TRANSFORMATIONS
3122  bool scalePage = false;
3123  double scale = 0.0;
3124  if(root->docWidth() > printer.width()) {
3125  scalePage = true;
3126  scale = ((double) printer.width())/((double) root->docWidth());
3127  pageHeight = (int) (pageHeight/scale);
3128  pageWidth = (int) (pageWidth/scale);
3129  headerHeight = (int) (headerHeight/scale);
3130  }
3131 #endif
3132  kDebug(6000) << "printing: scaled html width = " << pageWidth
3133  << " height = " << pageHeight << endl;
3134 
3135  root->setHeight(pageHeight);
3136  root->setPageBottom(pageHeight);
3137  root->setNeedsLayout(true);
3138  root->layoutIfNeeded();
3139 // m_part->slotDebugRenderTree();
3140 
3141  // Squeeze header to make it it on the page.
3142  if (printHeader)
3143  {
3144  int available_width = printer.width() - 10 -
3145  2 * qMax(p->boundingRect(0, 0, printer.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerLeft).width(),
3146  p->boundingRect(0, 0, printer.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerRight).width());
3147  if (available_width < 150)
3148  available_width = 150;
3149  int mid_width;
3150  int squeeze = 120;
3151  do {
3152  headerMid = KStringHandler::csqueeze(docname, squeeze);
3153  mid_width = p->boundingRect(0, 0, printer.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerMid).width();
3154  squeeze -= 10;
3155  } while (mid_width > available_width);
3156  }
3157 
3158  int top = 0;
3159  int bottom = 0;
3160  int page = 1;
3161  while(top < root->docHeight()) {
3162  if(top > 0) printer.newPage();
3163 #ifndef QT_NO_TRANSFORMATIONS
3164  if (scalePage)
3165  p->scale(scale, scale);
3166 #endif
3167  p->save();
3168  p->setClipRect(0, 0, pageWidth, headerHeight);
3169  if (printHeader)
3170  {
3171  int dy = p->fontMetrics().lineSpacing();
3172  p->setPen(Qt::black);
3173  p->setFont(headerFont);
3174 
3175  headerRight = QString("#%1").arg(page);
3176 
3177  p->drawText(0, 0, printer.width(), dy, Qt::AlignLeft, headerLeft);
3178  p->drawText(0, 0, printer.width(), dy, Qt::AlignHCenter, headerMid);
3179  p->drawText(0, 0, printer.width(), dy, Qt::AlignRight, headerRight);
3180  }
3181 
3182  p->restore();
3183  p->translate(0, headerHeight-top);
3184 
3185  bottom = top+pageHeight;
3186 
3187  root->setPageTop(top);
3188  root->setPageBottom(bottom);
3189  root->setPageNumber(page);
3190 
3191  root->layer()->paint(p, QRect(0, top, pageWidth, pageHeight));
3192  kDebug(6000) << "printed: page " << page <<" bottom At = " << bottom;
3193 
3194  top = bottom;
3195  p->resetTransform();
3196  page++;
3197  }
3198 
3199  p->end();
3200  delete p;
3201 
3202  // and now reset the layout to the usual one...
3203  root->setPagedMode(false);
3204  root->setStaticMode(false);
3205  d->paged = false;
3206  khtml::setPrintPainter( 0 );
3207  setMediaType( oldMediaType );
3208  m_part->xmlDocImpl()->setPaintDevice( this );
3209  m_part->xmlDocImpl()->styleSelector()->computeFontSizes(m_part->xmlDocImpl()->logicalDpiY(), m_part->fontScaleFactor());
3210  m_part->xmlDocImpl()->updateStyleSelector();
3211  viewport()->unsetCursor();
3212  }
3213 }
3214 
3215 void KHTMLView::slotPaletteChanged()
3216 {
3217  if(!m_part->xmlDocImpl()) return;
3218  DOM::DocumentImpl *document = m_part->xmlDocImpl();
3219  if (!document->isHTMLDocument()) return;
3220  khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(document->renderer());
3221  if(!root) return;
3222  root->style()->resetPalette();
3223  NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
3224  if(!body) return;
3225  body->setChanged(true);
3226  body->recalcStyle( NodeImpl::Force );
3227 }
3228 
3229 void KHTMLView::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
3230 {
3231  if(!m_part->xmlDocImpl()) return;
3232  khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
3233  if(!root) return;
3234 #ifdef SPEED_DEBUG
3235  d->firstRepaintPending = false;
3236 #endif
3237 
3238  QPaintDevice* opd = m_part->xmlDocImpl()->paintDevice();
3239  m_part->xmlDocImpl()->setPaintDevice(p->device());
3240  root->setPagedMode(true);
3241  root->setStaticMode(true);
3242  root->setWidth(rc.width());
3243 
3244  // save()
3245  QRegion creg = p->clipRegion();
3246  QTransform t = p->worldTransform();
3247  QRect w = p->window();
3248  QRect v = p->viewport();
3249  bool vte = p->viewTransformEnabled();
3250  bool wme = p->worldMatrixEnabled();
3251 
3252  p->setClipRect(rc);
3253  p->translate(rc.left(), rc.top());
3254  double scale = ((double) rc.width()/(double) root->docWidth());
3255  int height = (int) ((double) rc.height() / scale);
3256 #ifndef QT_NO_TRANSFORMATIONS
3257  p->scale(scale, scale);
3258 #endif
3259  root->setPageTop(yOff);
3260  root->setPageBottom(yOff+height);
3261 
3262  root->layer()->paint(p, QRect(0, yOff, root->docWidth(), height));
3263  if (more)
3264  *more = yOff + height < root->docHeight();
3265 
3266  // restore()
3267  p->setWorldTransform(t);
3268  p->setWindow(w);
3269  p->setViewport(v);
3270  p->setViewTransformEnabled( vte );
3271  p->setWorldMatrixEnabled( wme );
3272  if (!creg.isEmpty())
3273  p->setClipRegion( creg );
3274  else
3275  p->setClipRegion(QRegion(), Qt::NoClip);
3276 
3277  root->setPagedMode(false);
3278  root->setStaticMode(false);
3279  m_part->xmlDocImpl()->setPaintDevice( opd );
3280 }
3281 
3282 void KHTMLView::render(QPainter* p, const QRect& r, const QPoint& off)
3283 {
3284 #ifdef SPEED_DEBUG
3285  d->firstRepaintPending = false;
3286 #endif
3287  QRect clip(off.x()+r.x(), off.y()+r.y(),r.width(),r.height());
3288  if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
3289  p->fillRect(clip, palette().brush(QPalette::Active, QPalette::Base));
3290  return;
3291  }
3292  QPaintDevice* opd = m_part->xmlDocImpl()->paintDevice();
3293  m_part->xmlDocImpl()->setPaintDevice(p->device());
3294 
3295  // save()
3296  QRegion creg = p->clipRegion();
3297  QTransform t = p->worldTransform();
3298  QRect w = p->window();
3299  QRect v = p->viewport();
3300  bool vte = p->viewTransformEnabled();
3301  bool wme = p->worldMatrixEnabled();
3302 
3303  p->setClipRect(clip);
3304  QRect rect = r.translated(contentsX(),contentsY());
3305  p->translate(off.x()-contentsX(), off.y()-contentsY());
3306 
3307  m_part->xmlDocImpl()->renderer()->layer()->paint(p, rect);
3308 
3309  // restore()
3310  p->setWorldTransform(t);
3311  p->setWindow(w);
3312  p->setViewport(v);
3313  p->setViewTransformEnabled( vte );
3314  p->setWorldMatrixEnabled( wme );
3315  if (!creg.isEmpty())
3316  p->setClipRegion( creg );
3317  else
3318  p->setClipRegion(QRegion(), Qt::NoClip);
3319 
3320  m_part->xmlDocImpl()->setPaintDevice( opd );
3321 }
3322 
3323 void KHTMLView::setHasStaticBackground(bool partial)
3324 {
3325  // full static iframe is irreversible for now
3326  if (d->staticWidget == KHTMLViewPrivate::SBFull && m_kwp->isRedirected())
3327  return;
3328 
3329  d->staticWidget = partial ?
3330  KHTMLViewPrivate::SBPartial : KHTMLViewPrivate::SBFull;
3331 }
3332 
3333 void KHTMLView::setHasNormalBackground()
3334 {
3335  // full static iframe is irreversible for now
3336  if (d->staticWidget == KHTMLViewPrivate::SBFull && m_kwp->isRedirected())
3337  return;
3338 
3339  d->staticWidget = KHTMLViewPrivate::SBNone;
3340 }
3341 
3342 void KHTMLView::addStaticObject(bool fixed)
3343 {
3344  if (fixed)
3345  d->fixedObjectsCount++;
3346  else
3347  d->staticObjectsCount++;
3348 
3349  setHasStaticBackground( true /*partial*/ );
3350 }
3351 
3352 void KHTMLView::removeStaticObject(bool fixed)
3353 {
3354  if (fixed)
3355  d->fixedObjectsCount--;
3356  else
3357  d->staticObjectsCount--;
3358 
3359  assert( d->fixedObjectsCount >= 0 && d->staticObjectsCount >= 0 );
3360 
3361  if (!d->staticObjectsCount && !d->fixedObjectsCount)
3362  setHasNormalBackground();
3363  else
3364  setHasStaticBackground( true /*partial*/ );
3365 }
3366 
3367 void KHTMLView::setVerticalScrollBarPolicy( Qt::ScrollBarPolicy policy )
3368 {
3369 #ifndef KHTML_NO_SCROLLBARS
3370  d->vpolicy = policy;
3371  QScrollArea::setVerticalScrollBarPolicy(policy);
3372 #else
3373  Q_UNUSED( policy );
3374 #endif
3375 }
3376 
3377 void KHTMLView::setHorizontalScrollBarPolicy( Qt::ScrollBarPolicy policy )
3378 {
3379 #ifndef KHTML_NO_SCROLLBARS
3380  d->hpolicy = policy;
3381  QScrollArea::setHorizontalScrollBarPolicy(policy);
3382 #else
3383  Q_UNUSED( policy );
3384 #endif
3385 }
3386 
3387 void KHTMLView::restoreScrollBar()
3388 {
3389  int ow = visibleWidth();
3390  QScrollArea::setVerticalScrollBarPolicy(d->vpolicy);
3391  if (visibleWidth() != ow)
3392  layout();
3393  d->prevScrollbarVisible = verticalScrollBar()->isVisible();
3394 }
3395 
3396 QStringList KHTMLView::formCompletionItems(const QString &name) const
3397 {
3398  if (!m_part->settings()->isFormCompletionEnabled())
3399  return QStringList();
3400  if (!d->formCompletions)
3401  d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions"));
3402  return d->formCompletions->group("").readEntry(name, QStringList());
3403 }
3404 
3405 void KHTMLView::clearCompletionHistory(const QString& name)
3406 {
3407  if (!d->formCompletions)
3408  {
3409  d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions"));
3410  }
3411  d->formCompletions->group("").writeEntry(name, "");
3412  d->formCompletions->sync();
3413 }
3414 
3415 void KHTMLView::addFormCompletionItem(const QString &name, const QString &value)
3416 {
3417  if (!m_part->settings()->isFormCompletionEnabled())
3418  return;
3419  // don't store values that are all numbers or just numbers with
3420  // dashes or spaces as those are likely credit card numbers or
3421  // something similar
3422  bool cc_number(true);
3423  for ( int i = 0; i < value.length(); ++i)
3424  {
3425  QChar c(value[i]);
3426  if (!c.isNumber() && c != '-' && !c.isSpace())
3427  {
3428  cc_number = false;
3429  break;
3430  }
3431  }
3432  if (cc_number)
3433  return;
3434  QStringList items = formCompletionItems(name);
3435  if (!items.contains(value))
3436  items.prepend(value);
3437  while ((int)items.count() > m_part->settings()->maxFormCompletionItems())
3438  items.erase(items.isEmpty() ? items.end() : --items.end());
3439  d->formCompletions->group("").writeEntry(name, items);
3440 }
3441 
3442 void KHTMLView::addNonPasswordStorableSite(const QString& host)
3443 {
3444  if (!d->formCompletions) {
3445  d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions"));
3446  }
3447 
3448  KConfigGroup cg( d->formCompletions, "NonPasswordStorableSites");
3449  QStringList sites = cg.readEntry("Sites", QStringList());
3450  sites.append(host);
3451  cg.writeEntry("Sites", sites);
3452  cg.sync();
3453 }
3454 
3455 
3456 void KHTMLView::delNonPasswordStorableSite(const QString& host)
3457 {
3458  if (!d->formCompletions) {
3459  d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions"));
3460  }
3461 
3462  KConfigGroup cg( d->formCompletions, "NonPasswordStorableSites");
3463  QStringList sites = cg.readEntry("Sites", QStringList());
3464  sites.removeOne(host);
3465  cg.writeEntry("Sites", sites);
3466  cg.sync();
3467 }
3468 
3469 bool KHTMLView::nonPasswordStorableSite(const QString& host) const
3470 {
3471  if (!d->formCompletions) {
3472  d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions"));
3473  }
3474  QStringList sites = d->formCompletions->group( "NonPasswordStorableSites" ).readEntry("Sites", QStringList());
3475  return (sites.indexOf(host) != -1);
3476 }
3477 
3478 // returns true if event should be swallowed
3479 bool KHTMLView::dispatchMouseEvent(int eventId, DOM::NodeImpl *targetNode,
3480  DOM::NodeImpl *targetNodeNonShared, bool cancelable,
3481  int detail,QMouseEvent *_mouse, bool setUnder,
3482  int mouseEventType, int orient)
3483 {
3484  // if the target node is a text node, dispatch on the parent node - rdar://4196646 (and #76948)
3485  if (targetNode && targetNode->isTextNode())
3486  targetNode = targetNode->parentNode();
3487 
3488  if (d->underMouse)
3489  d->underMouse->deref();
3490  d->underMouse = targetNode;
3491  if (d->underMouse)
3492  d->underMouse->ref();
3493 
3494  if (d->underMouseNonShared)
3495  d->underMouseNonShared->deref();
3496  d->underMouseNonShared = targetNodeNonShared;
3497  if (d->underMouseNonShared)
3498  d->underMouseNonShared->ref();
3499 
3500  bool isWheelEvent = (mouseEventType == DOM::NodeImpl::MouseWheel);
3501 
3502  int exceptioncode = 0;
3503  int pageX = _mouse->x();
3504  int pageY = _mouse->y();
3505  revertTransforms(pageX, pageY);
3506  int clientX = pageX - contentsX();
3507  int clientY = pageY - contentsY();
3508  int screenX = _mouse->globalX();
3509  int screenY = _mouse->globalY();
3510  int button = -1;
3511  switch (_mouse->button()) {
3512  case Qt::LeftButton:
3513  button = 0;
3514  break;
3515  case Qt::MidButton:
3516  button = 1;
3517  break;
3518  case Qt::RightButton:
3519  button = 2;
3520  break;
3521  default:
3522  break;
3523  }
3524  if (d->accessKeysEnabled && d->accessKeysPreActivate && button!=-1)
3525  d->accessKeysPreActivate=false;
3526 
3527  bool ctrlKey = (_mouse->modifiers() & Qt::ControlModifier);
3528  bool altKey = (_mouse->modifiers() & Qt::AltModifier);
3529  bool shiftKey = (_mouse->modifiers() & Qt::ShiftModifier);
3530  bool metaKey = (_mouse->modifiers() & Qt::MetaModifier);
3531 
3532  // mouseout/mouseover
3533  if (setUnder && d->oldUnderMouse != targetNode) {
3534  if (d->oldUnderMouse && d->oldUnderMouse->document() != m_part->xmlDocImpl()) {
3535  d->oldUnderMouse->deref();
3536  d->oldUnderMouse = 0;
3537  }
3538  // send mouseout event to the old node
3539  if (d->oldUnderMouse) {
3540  // send mouseout event to the old node
3541  MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOUT_EVENT,
3542  true,true,m_part->xmlDocImpl()->defaultView(),
3543  0,screenX,screenY,clientX,clientY,pageX, pageY,
3544  ctrlKey,altKey,shiftKey,metaKey,
3545  button,targetNode);
3546  me->ref();
3547  d->oldUnderMouse->dispatchEvent(me,exceptioncode,true);
3548  me->deref();
3549  }
3550  // send mouseover event to the new node
3551  if (targetNode) {
3552  MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOVER_EVENT,
3553  true,true,m_part->xmlDocImpl()->defaultView(),
3554  0,screenX,screenY,clientX,clientY,pageX, pageY,
3555  ctrlKey,altKey,shiftKey,metaKey,
3556  button,d->oldUnderMouse);
3557 
3558  me->ref();
3559  targetNode->dispatchEvent(me,exceptioncode,true);
3560  me->deref();
3561  }
3562  if (d->oldUnderMouse)
3563  d->oldUnderMouse->deref();
3564  d->oldUnderMouse = targetNode;
3565  if (d->oldUnderMouse)
3566  d->oldUnderMouse->ref();
3567  }
3568 
3569  bool swallowEvent = false;
3570 
3571  if (targetNode) {
3572  // if the target node is a disabled widget, we don't want any full-blown mouse events
3573  if (targetNode->isGenericFormElement()
3574  && static_cast<HTMLGenericFormElementImpl*>(targetNode)->disabled())
3575  return true;
3576 
3577  // send the actual event
3578  bool dblclick = ( eventId == EventImpl::CLICK_EVENT &&
3579  _mouse->type() == QEvent::MouseButtonDblClick );
3580  MouseEventImpl *me = new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
3581  true,cancelable,m_part->xmlDocImpl()->defaultView(),
3582  detail,screenX,screenY,clientX,clientY,pageX, pageY,
3583  ctrlKey,altKey,shiftKey,metaKey,
3584  button,0, isWheelEvent ? 0 : _mouse, dblclick,
3585  isWheelEvent ? static_cast<MouseEventImpl::Orientation>(orient) : MouseEventImpl::ONone );
3586  me->ref();
3587  if ( !d->m_mouseEventsTarget && RenderLayer::gScrollBar && eventId == EventImpl::MOUSEDOWN_EVENT )
3588  // button is pressed inside a layer scrollbar, so make it the target for future mousemove events until released
3589  d->m_mouseEventsTarget = RenderLayer::gScrollBar;
3590  if ( d->m_mouseEventsTarget && qobject_cast<QScrollBar*>(d->m_mouseEventsTarget) &&
3591  dynamic_cast<KHTMLWidget*>(static_cast<QWidget*>(d->m_mouseEventsTarget)) ) {
3592  // we have a sticky mouse event target and it is a layer's scrollbar. Forward events manually.
3593  // ### should use the dom
3594  KHTMLWidget*w = dynamic_cast<KHTMLWidget*>(static_cast<QWidget*>(d->m_mouseEventsTarget));
3595  QPoint p = w->m_kwp->absolutePos();
3596  QMouseEvent fw(_mouse->type(), QPoint(pageX, pageY)-p, _mouse->button(), _mouse->buttons(), _mouse->modifiers());
3597  static_cast<RenderWidget::EventPropagator *>(static_cast<QWidget*>(d->m_mouseEventsTarget))->sendEvent(&fw);
3598  if (_mouse->type() == QMouseEvent::MouseButtonPress && _mouse->button() == Qt::RightButton) {
3599  QContextMenuEvent cme(QContextMenuEvent::Mouse, p);
3600  static_cast<RenderWidget::EventPropagator *>(static_cast<QWidget*>(d->m_mouseEventsTarget))->sendEvent(&cme);
3601  d->m_mouseEventsTarget = 0;
3602  }
3603  swallowEvent = true;
3604  } else {
3605  targetNode->dispatchEvent(me,exceptioncode,true);
3606  bool defaultHandled = me->defaultHandled();
3607  if (defaultHandled || me->defaultPrevented())
3608  swallowEvent = true;
3609  }
3610  if (eventId == EventImpl::MOUSEDOWN_EVENT && !me->defaultPrevented()) {
3611  // Focus should be shifted on mouse down, not on a click. -dwh
3612  // Blur current focus node when a link/button is clicked; this
3613  // is expected by some sites that rely on onChange handlers running
3614  // from form fields before the button click is processed.
3615  DOM::NodeImpl* nodeImpl = targetNode;
3616  for ( ; nodeImpl && !nodeImpl->isFocusable(); nodeImpl = nodeImpl->parentNode())
3617  {}
3618  if (nodeImpl && nodeImpl->isMouseFocusable())
3619  m_part->xmlDocImpl()->setFocusNode(nodeImpl);
3620  else if (!nodeImpl || !nodeImpl->focused())
3621  m_part->xmlDocImpl()->setFocusNode(0);
3622  }
3623  me->deref();
3624  }
3625 
3626  return swallowEvent;
3627 }
3628 
3629 void KHTMLView::setIgnoreWheelEvents( bool e )
3630 {
3631  d->ignoreWheelEvents = e;
3632 }
3633 
3634 #ifndef QT_NO_WHEELEVENT
3635 
3636 void KHTMLView::wheelEvent(QWheelEvent* e)
3637 {
3638  // check if we should reset the state of the indicator describing if
3639  // we are currently scrolling the view as a result of wheel events
3640  if (d->scrollingFromWheel != QPoint(-1,-1) && d->scrollingFromWheel != QCursor::pos())
3641  d->scrollingFromWheel = d->scrollingFromWheelTimerId ? QCursor::pos() : QPoint(-1,-1);
3642 
3643  if (d->accessKeysEnabled && d->accessKeysPreActivate) d->accessKeysPreActivate=false;
3644 
3645  if ( ( e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier )
3646  {
3647  emit zoomView( - e->delta() );
3648  e->accept();
3649  }
3650  else if (d->firstLayoutPending)
3651  {
3652  e->accept();
3653  }
3654  else if( !m_kwp->isRedirected() &&
3655  ( (e->orientation() == Qt::Vertical &&
3656  ((d->ignoreWheelEvents && !verticalScrollBar()->isVisible())
3657  || (e->delta() > 0 && contentsY() <= 0)
3658  || (e->delta() < 0 && contentsY() >= contentsHeight() - visibleHeight())))
3659  ||
3660  (e->orientation() == Qt::Horizontal &&
3661  ((d->ignoreWheelEvents && !horizontalScrollBar()->isVisible())
3662  || (e->delta() > 0 && contentsX() <=0)
3663  || (e->delta() < 0 && contentsX() >= contentsWidth() - visibleWidth()))))
3664  && m_part->parentPart())
3665  {
3666  if ( m_part->parentPart()->view() )
3667  m_part->parentPart()->view()->wheelEvent( e );
3668  e->ignore();
3669  }
3670  else
3671  {
3672  int xm = e->x();
3673  int ym = e->y();
3674  revertTransforms(xm, ym);
3675 
3676  DOM::NodeImpl::MouseEvent mev( e->buttons(), DOM::NodeImpl::MouseWheel );
3677  m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
3678 
3679  MouseEventImpl::Orientation o = MouseEventImpl::OVertical;
3680  if (e->orientation() == Qt::Horizontal)
3681  o = MouseEventImpl::OHorizontal;
3682 
3683  QMouseEvent _mouse(QEvent::MouseMove, e->pos(), Qt::NoButton, e->buttons(), e->modifiers());
3684  bool swallow = dispatchMouseEvent(EventImpl::KHTML_MOUSEWHEEL_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),
3685  true,-e->delta()/40,&_mouse,true,DOM::NodeImpl::MouseWheel,o);
3686 
3687  if (swallow)
3688  return;
3689 
3690  d->scrollBarMoved = true;
3691  d->scrollingFromWheel = QCursor::pos();
3692  if (d->smoothScrollMode != SSMDisabled)
3693  d->shouldSmoothScroll = true;
3694  if (d->scrollingFromWheelTimerId)
3695  killTimer(d->scrollingFromWheelTimerId);
3696  d->scrollingFromWheelTimerId = startTimer(400);
3697 
3698  if (m_part->parentPart()) {
3699  // don't propagate if we are a sub-frame and our scrollbars are already at end of range
3700  bool h = (static_cast<QWheelEvent*>(e)->orientation() == Qt::Horizontal);
3701  bool d = (static_cast<QWheelEvent*>(e)->delta() < 0);
3702  QScrollBar* hsb = horizontalScrollBar();
3703  QScrollBar* vsb = verticalScrollBar();
3704  if ( (h && ((d && hsb->value() == hsb->maximum()) || (!d && hsb->value() == hsb->minimum()))) ||
3705  (!h && ((d && vsb->value() == vsb->maximum()) || (!d && vsb->value() == vsb->minimum()))) ) {
3706  e->accept();
3707  return;
3708  }
3709  }
3710  QScrollArea::wheelEvent( e );
3711  }
3712 
3713 }
3714 #endif
3715 
3716 void KHTMLView::dragEnterEvent( QDragEnterEvent* ev )
3717 {
3718  // Still overridden for BC reasons only...
3719  QScrollArea::dragEnterEvent( ev );
3720 }
3721 
3722 void KHTMLView::dropEvent( QDropEvent *ev )
3723 {
3724  // Still overridden for BC reasons only...
3725  QScrollArea::dropEvent( ev );
3726 }
3727 
3728 void KHTMLView::focusInEvent( QFocusEvent *e )
3729 {
3730  DOM::NodeImpl* fn = m_part->xmlDocImpl() ? m_part->xmlDocImpl()->focusNode() : 0;
3731  if (fn && fn->renderer() && fn->renderer()->isWidget() &&
3732  (e->reason() != Qt::MouseFocusReason) &&
3733  static_cast<khtml::RenderWidget*>(fn->renderer())->widget())
3734  static_cast<khtml::RenderWidget*>(fn->renderer())->widget()->setFocus();
3735  m_part->setSelectionVisible();
3736  QScrollArea::focusInEvent( e );
3737 }
3738 
3739 void KHTMLView::focusOutEvent( QFocusEvent *e )
3740 {
3741  if (m_part) {
3742  m_part->stopAutoScroll();
3743  m_part->setSelectionVisible(false);
3744  }
3745 
3746  if ( d->cursorIconWidget )
3747  d->cursorIconWidget->hide();
3748 
3749  QScrollArea::focusOutEvent( e );
3750 }
3751 
3752 void KHTMLView::scrollContentsBy( int dx, int dy )
3753 {
3754  if (!dx && !dy) return;
3755 
3756  if ( !d->firstLayoutPending && !d->complete && m_part->xmlDocImpl() &&
3757  d->layoutSchedulingEnabled) {
3758  // contents scroll while we are not complete: we need to check our layout *now*
3759  khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>( m_part->xmlDocImpl()->renderer() );
3760  if (root && root->needsLayout()) {
3761  unscheduleRelayout();
3762  layout();
3763  }
3764  }
3765 
3766  if ( d->shouldSmoothScroll && d->smoothScrollMode != SSMDisabled && m_part->xmlDocImpl() &&
3767  m_part->xmlDocImpl()->renderer() && (d->smoothScrollMode != SSMWhenEfficient || d->smoothScrollMissedDeadlines != sWayTooMany)) {
3768 
3769  bool doSmoothScroll = (!d->staticWidget || d->smoothScrollMode == SSMEnabled);
3770 
3771  int numStaticPixels = 0;
3772  QRegion r = static_cast<RenderCanvas*>(m_part->xmlDocImpl()->renderer())->staticRegion();
3773 
3774  // only do smooth scrolling if static region is relatively small
3775  if (!doSmoothScroll && d->staticWidget == KHTMLViewPrivate::SBPartial && r.rects().size() <= 10) {
3776  foreach(const QRect &rr, r.rects())
3777  numStaticPixels += rr.width()*rr.height();
3778  if ((numStaticPixels < sSmoothScrollMinStaticPixels) || (numStaticPixels*8 < visibleWidth()*visibleHeight()))
3779  doSmoothScroll = true;
3780  }
3781  if (doSmoothScroll) {
3782  setupSmoothScrolling(dx, dy);
3783  return;
3784  }
3785  }
3786 
3787  if ( underMouse() && QToolTip::isVisible() )
3788  QToolTip::hideText();
3789 
3790  if (!d->scrollingSelf) {
3791  d->scrollBarMoved = true;
3792  d->contentsMoving = true;
3793  // ensure quick reset of contentsMoving flag
3794  scheduleRepaint(0, 0, 0, 0);
3795  }
3796 
3797  if (m_part->xmlDocImpl() && m_part->xmlDocImpl()->documentElement()) {
3798  m_part->xmlDocImpl()->documentElement()->dispatchHTMLEvent(EventImpl::SCROLL_EVENT, true, false);
3799  }
3800 
3801  if (QApplication::isRightToLeft())
3802  dx = -dx;
3803 
3804  if (!d->smoothScrolling) {
3805  d->updateContentsXY();
3806  } else {
3807  d->contentsX -= dx;
3808  d->contentsY -= dy;
3809  }
3810  if (widget()->pos() != QPoint(0,0)) {
3811  kDebug(6000) << "Static widget wasn't positioned at (0,0). This should NOT happen. Please report this event to developers.";
3812  kDebug(6000) << kBacktrace();
3813  widget()->move(0,0);
3814  }
3815 
3816  QWidget *w = widget();
3817  QPoint off;
3818  if (m_kwp->isRedirected()) {
3819  // This is a redirected sub frame. Translate to root view context
3820  KHTMLView* v = m_kwp->rootViewPos( off );
3821  if (v)
3822  w = v->widget();
3823  off = viewport()->mapTo(this, off);
3824  }
3825 
3826  if ( d->staticWidget ) {
3827 
3828  // now remove from view the external widgets that must have completely
3829  // disappeared after dx/dy scroll delta is effective
3830  if (!d->visibleWidgets.isEmpty())
3831  checkExternalWidgetsPosition();
3832 
3833  if ( d->staticWidget == KHTMLViewPrivate::SBPartial
3834  && m_part->xmlDocImpl() && m_part->xmlDocImpl()->renderer() ) {
3835  // static objects might be selectively repainted, like stones in flowing water
3836  QRegion r = static_cast<RenderCanvas*>(m_part->xmlDocImpl()->renderer())->staticRegion();
3837  r.translate( -contentsX(), -contentsY());
3838  QVector<QRect> ar = r.rects();
3839 
3840  for (int i = 0; i < ar.size() ; ++i) {
3841  widget()->update( ar[i] );
3842  }
3843  r = QRegion(QRect(0, 0, visibleWidth(), visibleHeight())) - r;
3844  ar = r.rects();
3845  for (int i = 0; i < ar.size() ; ++i) {
3846  w->scroll( dx, dy, ar[i].translated(off) );
3847  }
3848  d->scrollExternalWidgets(dx, dy);
3849  } else {
3850  // we can't avoid a full update
3851  widget()->update();
3852  }
3853  if (d->accessKeysActivated)
3854  d->scrollAccessKeys(dx, dy);
3855 
3856  return;
3857  }
3858 
3859  if (m_kwp->isRedirected()) {
3860  const QRect rect(off.x(), off.y(), visibleWidth() * d->zoomLevel / 100, visibleHeight() * d->zoomLevel / 100);
3861  w->scroll(dx, dy, rect);
3862  if (d->zoomLevel != 100) {
3863  w->update(rect); // without this update we are getting bad rendering when an iframe is zoomed in
3864  }
3865  } else {
3866  widget()->scroll(dx, dy, widget()->rect() & viewport()->rect());
3867  }
3868 
3869  d->scrollExternalWidgets(dx, dy);
3870  if (d->accessKeysActivated)
3871  d->scrollAccessKeys(dx, dy);
3872 }
3873 
3874 void KHTMLView::setupSmoothScrolling(int dx, int dy)
3875 {
3876  // old or minimum speed
3877  int ddx = qMax(d->steps ? abs(d->dx)/d->steps : 0,3);
3878  int ddy = qMax(d->steps ? abs(d->dy)/d->steps : 0,3);
3879 
3880  // full scroll is remaining scroll plus new scroll
3881  d->dx = d->dx + dx;
3882  d->dy = d->dy + dy;
3883 
3884  if (d->dx == 0 && d->dy == 0) {
3885  d->stopScrolling();
3886  return;
3887  }
3888 
3889  d->steps = (sSmoothScrollTime-1)/sSmoothScrollTick + 1;
3890 
3891  if (qMax(abs(d->dx), abs(d->dy)) / d->steps < qMax(ddx,ddy)) {
3892  // Don't move slower than average 4px/step in minimum one direction
3893  // This means fewer than normal steps
3894  d->steps = qMax((abs(d->dx)+ddx-1)/ddx, (abs(d->dy)+ddy-1)/ddy);
3895  if (d->steps < 1) d->steps = 1;
3896  }
3897 
3898  d->smoothScrollStopwatch.start();
3899  if (!d->smoothScrolling) {
3900  d->startScrolling();
3901  scrollTick();
3902  }
3903 }
3904 
3905 void KHTMLView::scrollTick() {
3906  if (d->dx == 0 && d->dy == 0) {
3907  d->stopScrolling();
3908  return;
3909  }
3910 
3911  if (d->steps < 1) d->steps = 1;
3912  int takesteps = d->smoothScrollStopwatch.restart() / sSmoothScrollTick;
3913  int scroll_x = 0;
3914  int scroll_y = 0;
3915  if (takesteps < 1) takesteps = 1;
3916  if (takesteps > d->steps) takesteps = d->steps;
3917  for(int i = 0; i < takesteps; i++) {
3918  int ddx = (d->dx / (d->steps+1)) * 2;
3919  int ddy = (d->dy / (d->steps+1)) * 2;
3920 
3921  // limit step to requested scrolling distance
3922  if (abs(ddx) > abs(d->dx)) ddx = d->dx;
3923  if (abs(ddy) > abs(d->dy)) ddy = d->dy;
3924 
3925  // update remaining scroll
3926  d->dx -= ddx;
3927  d->dy -= ddy;
3928  scroll_x += ddx;
3929  scroll_y += ddy;
3930  d->steps--;
3931  }
3932 
3933  d->shouldSmoothScroll = false;
3934  scrollContentsBy(scroll_x, scroll_y);
3935 
3936  if (takesteps < 2) {
3937  d->smoothScrollMissedDeadlines = 0;
3938  } else {
3939  if (d->smoothScrollMissedDeadlines != sWayTooMany &&
3940  (!m_part->xmlDocImpl() || !m_part->xmlDocImpl()->parsing())) {
3941  d->smoothScrollMissedDeadlines++;
3942  if (d->smoothScrollMissedDeadlines >= sMaxMissedDeadlines) {
3943  // we missed many deadlines in a row!
3944  // time to signal we had enough..
3945  d->smoothScrollMissedDeadlines = sWayTooMany;
3946  }
3947  }
3948  }
3949 }
3950 
3951 
3952 void KHTMLView::addChild(QWidget * child, int x, int y)
3953 {
3954  if (!child)
3955  return;
3956 
3957  if (child->parent() != widget())
3958  child->setParent( widget() );
3959 
3960  // ### handle pseudo-zooming of non-redirected widgets (e.g. just resize'em)
3961 
3962  child->move(x-contentsX(), y-contentsY());
3963 }
3964 
3965 void KHTMLView::timerEvent ( QTimerEvent *e )
3966 {
3967 // kDebug() << "timer event " << e->timerId();
3968  if ( e->timerId() == d->scrollTimerId ) {
3969  if( d->scrollSuspended )
3970  return;
3971  switch (d->scrollDirection) {
3972  case KHTMLViewPrivate::ScrollDown:
3973  if (contentsY() + visibleHeight () >= contentsHeight())
3974  d->newScrollTimer(this, 0);
3975  else
3976  verticalScrollBar()->setValue( verticalScrollBar()->value() +d->scrollBy );
3977  break;
3978  case KHTMLViewPrivate::ScrollUp:
3979  if (contentsY() <= 0)
3980  d->newScrollTimer(this, 0);
3981  else
3982  verticalScrollBar()->setValue( verticalScrollBar()->value() -d->scrollBy );
3983  break;
3984  case KHTMLViewPrivate::ScrollRight:
3985  if (contentsX() + visibleWidth () >= contentsWidth())
3986  d->newScrollTimer(this, 0);
3987  else
3988  horizontalScrollBar()->setValue( horizontalScrollBar()->value() +d->scrollBy );
3989  break;
3990  case KHTMLViewPrivate::ScrollLeft:
3991  if (contentsX() <= 0)
3992  d->newScrollTimer(this, 0);
3993  else
3994  horizontalScrollBar()->setValue( horizontalScrollBar()->value() -d->scrollBy );
3995  break;
3996  }
3997  return;
3998  }
3999  else if ( e->timerId() == d->scrollingFromWheelTimerId ) {
4000  killTimer( d->scrollingFromWheelTimerId );
4001  d->scrollingFromWheelTimerId = 0;
4002  } else if ( e->timerId() == d->layoutTimerId ) {
4003  if (d->firstLayoutPending && d->layoutAttemptCounter < 4
4004  && (!m_part->xmlDocImpl() || !m_part->xmlDocImpl()->readyForLayout())) {
4005  d->layoutAttemptCounter++;
4006  killTimer(d->layoutTimerId);
4007  d->layoutTimerId = 0;
4008  scheduleRelayout();
4009  return;
4010  }
4011  layout();
4012  d->scheduledLayoutCounter++;
4013  if (d->firstLayoutPending) {
4014  d->firstLayoutPending = false;
4015  verticalScrollBar()->setEnabled( true );
4016  horizontalScrollBar()->setEnabled( true );
4017  }
4018  }
4019 
4020  d->contentsMoving = false;
4021  if( m_part->xmlDocImpl() ) {
4022  DOM::DocumentImpl *document = m_part->xmlDocImpl();
4023  khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer());
4024 
4025  if ( root && root->needsLayout() ) {
4026  if (d->repaintTimerId)
4027  killTimer(d->repaintTimerId);
4028  d->repaintTimerId = 0;
4029  scheduleRelayout();
4030  return;
4031  }
4032  }
4033 
4034  if (d->repaintTimerId)
4035  killTimer(d->repaintTimerId);
4036  d->repaintTimerId = 0;
4037 
4038  QRect updateRegion;
4039  const QVector<QRect> rects = d->updateRegion.rects();
4040 
4041  d->updateRegion = QRegion();
4042 
4043  if ( rects.size() )
4044  updateRegion = rects[0];
4045 
4046  for ( int i = 1; i < rects.size(); ++i ) {
4047  QRect newRegion = updateRegion.unite(rects[i]);
4048  if (2*newRegion.height() > 3*updateRegion.height() )
4049  {
4050  repaintContents( updateRegion );
4051  updateRegion = rects[i];
4052  }
4053  else
4054  updateRegion = newRegion;
4055  }
4056 
4057  if ( !updateRegion.isNull() )
4058  repaintContents( updateRegion );
4059 
4060  // As widgets can only be accurately positioned during painting, every layout might
4061  // dissociate a widget from its RenderWidget. E.g: if a RenderWidget was visible before layout, but the layout
4062  // pushed it out of the viewport, it will not be repainted, and consequently it's associated widget won't be repositioned.
4063  // Thus we need to check each supposedly 'visible' widget at the end of layout, and remove it in case it's no more in sight.
4064 
4065  if (d->dirtyLayout && !d->visibleWidgets.isEmpty())
4066  checkExternalWidgetsPosition();
4067 
4068  d->dirtyLayout = false;
4069 
4070  emit repaintAccessKeys();
4071  if (d->emitCompletedAfterRepaint) {
4072  bool full = d->emitCompletedAfterRepaint == KHTMLViewPrivate::CSFull;
4073  d->emitCompletedAfterRepaint = KHTMLViewPrivate::CSNone;
4074  if ( full )
4075  emit m_part->completed();
4076  else
4077  emit m_part->completed(true);
4078  }
4079 }
4080 
4081 void KHTMLView::checkExternalWidgetsPosition()
4082 {
4083  QWidget* w;
4084  QRect visibleRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
4085  QList<RenderWidget*> toRemove;
4086  QHashIterator<void*, QWidget*> it(d->visibleWidgets);
4087  while (it.hasNext()) {
4088  int xp = 0, yp = 0;
4089  it.next();
4090  RenderWidget* rw = static_cast<RenderWidget*>( it.key() );
4091  if (!rw->absolutePosition(xp, yp) ||
4092  !visibleRect.intersects(QRect(xp, yp, it.value()->width(), it.value()->height())))
4093  toRemove.append(rw);
4094  }
4095  foreach (RenderWidget* r, toRemove)
4096  if ( (w = d->visibleWidgets.take(r) ) )
4097  w->move( 0, -500000);
4098 }
4099 
4100 void KHTMLView::scheduleRelayout(khtml::RenderObject * /*clippedObj*/)
4101 {
4102  if (!d->layoutSchedulingEnabled || d->layoutTimerId)
4103  return;
4104 
4105  int time = 0;
4106  if (d->firstLayoutPending) {
4107  // Any repaint happening while we have no content blanks the viewport ("white flash").
4108  // Hence the need to delay the first layout as much as we can.
4109  // Only if the document gets stuck for too long in incomplete state will we allow the blanking.
4110  time = d->layoutAttemptCounter ?
4111  sLayoutAttemptDelay + sLayoutAttemptIncrement*d->layoutAttemptCounter : sFirstLayoutDelay;
4112  } else if (m_part->xmlDocImpl() && m_part->xmlDocImpl()->parsing()) {
4113  // Delay between successive layouts in parsing mode.
4114  // Increment reflects the decaying importance of visual feedback over time.
4115  time = qMin(2000, sParsingLayoutsInterval + d->scheduledLayoutCounter*sParsingLayoutsIncrement);
4116  }
4117  d->layoutTimerId = startTimer( time );
4118 }
4119 
4120 void KHTMLView::unscheduleRelayout()
4121 {
4122  if (!d->layoutTimerId)
4123  return;
4124 
4125  killTimer(d->layoutTimerId);
4126  d->layoutTimerId = 0;
4127 }
4128 
4129 void KHTMLView::unscheduleRepaint()
4130 {
4131  if (!d->repaintTimerId)
4132  return;
4133 
4134  killTimer(d->repaintTimerId);
4135  d->repaintTimerId = 0;
4136 }
4137 
4138 void KHTMLView::scheduleRepaint(int x, int y, int w, int h, bool asap)
4139 {
4140  bool parsing = !m_part->xmlDocImpl() || m_part->xmlDocImpl()->parsing();
4141 
4142 // kDebug() << "parsing " << parsing;
4143 // kDebug() << "complete " << d->complete;
4144 
4145  int time = parsing && !d->firstLayoutPending ? 150 : (!asap ? ( !d->complete ? 80 : 20 ) : 0);
4146 
4147 #ifdef DEBUG_FLICKER
4148  QPainter p;
4149  p.begin( viewport() );
4150 
4151  int vx, vy;
4152  contentsToViewport( x, y, vx, vy );
4153  p.fillRect( vx, vy, w, h, Qt::red );
4154  p.end();
4155 #endif
4156 
4157  d->updateRegion = d->updateRegion.unite(QRect(x,y,w,h));
4158 
4159  if (asap && !parsing)
4160  unscheduleRepaint();
4161 
4162  if ( !d->repaintTimerId )
4163  d->repaintTimerId = startTimer( time );
4164 
4165 // kDebug() << "starting timer " << time;
4166 }
4167 
4168 void KHTMLView::complete( bool pendingAction )
4169 {
4170 // kDebug() << "KHTMLView::complete()";
4171 
4172  d->complete = true;
4173 
4174  // is there a relayout pending?
4175  if (d->layoutTimerId)
4176  {
4177 // kDebug() << "requesting relayout now";
4178  // do it now
4179  killTimer(d->layoutTimerId);
4180  d->layoutTimerId = startTimer( 0 );
4181  d->emitCompletedAfterRepaint = pendingAction ?
4182  KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull;
4183  }
4184 
4185  // is there a repaint pending?
4186  if (d->repaintTimerId)
4187  {
4188 // kDebug() << "requesting repaint now";
4189  // do it now
4190  killTimer(d->repaintTimerId);
4191  d->repaintTimerId = startTimer( 0 );
4192  d->emitCompletedAfterRepaint = pendingAction ?
4193  KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull;
4194  }
4195 
4196  if (!d->emitCompletedAfterRepaint)
4197  {
4198  if (!pendingAction)
4199  emit m_part->completed();
4200  else
4201  emit m_part->completed(true);
4202  }
4203 
4204 }
4205 
4206 void KHTMLView::updateScrollBars()
4207 {
4208  const QWidget *view = widget();
4209  if (!view)
4210  return;
4211 
4212  QSize p = viewport()->size();
4213  QSize m = maximumViewportSize();
4214 
4215  if (m.expandedTo(view->size()) == m)
4216  p = m; // no scroll bars needed
4217 
4218  QSize v = view->size();
4219  horizontalScrollBar()->setRange(0, v.width() - p.width());
4220  horizontalScrollBar()->setPageStep(p.width());
4221  verticalScrollBar()->setRange(0, v.height() - p.height());
4222  verticalScrollBar()->setPageStep(p.height());
4223  if (!d->smoothScrolling) {
4224  d->updateContentsXY();
4225  }
4226 }
4227 
4228 void KHTMLView::slotMouseScrollTimer()
4229 {
4230  horizontalScrollBar()->setValue( horizontalScrollBar()->value() +d->m_mouseScroll_byX );
4231  verticalScrollBar()->setValue( verticalScrollBar()->value() +d->m_mouseScroll_byY);
4232 }
4233 
4234 
4235 static DOM::Position positionOfLineBoundary(const DOM::Position &pos, bool toEnd)
4236 {
4237  Selection sel = pos;
4238  sel.expandUsingGranularity(Selection::LINE);
4239  return toEnd ? sel.end() : sel.start();
4240 }
4241 
4242 inline static DOM::Position positionOfLineBegin(const DOM::Position &pos)
4243 {
4244  return positionOfLineBoundary(pos, false);
4245 }
4246 
4247 inline static DOM::Position positionOfLineEnd(const DOM::Position &pos)
4248 {
4249  return positionOfLineBoundary(pos, true);
4250 }
4251 
4252 bool KHTMLView::caretKeyPressEvent(QKeyEvent *_ke)
4253 {
4254  EditorContext *ec = &m_part->d->editor_context;
4255  Selection &caret = ec->m_selection;
4256  Position old_pos = caret.caretPos();
4257  Position pos = old_pos;
4258  bool recalcXPos = true;
4259  bool handled = true;
4260 
4261  bool ctrl = _ke->modifiers() & Qt::ControlModifier;
4262  bool shift = _ke->modifiers() & Qt::ShiftModifier;
4263 
4264  switch(_ke->key()) {
4265 
4266  // -- Navigational keys
4267  case Qt::Key_Down:
4268  pos = old_pos.nextLinePosition(caret.xPosForVerticalArrowNavigation(Selection::EXTENT));
4269  recalcXPos = false;
4270  break;
4271 
4272  case Qt::Key_Up:
4273  pos = old_pos.previousLinePosition(caret.xPosForVerticalArrowNavigation(Selection::EXTENT));
4274  recalcXPos = false;
4275  break;
4276 
4277  case Qt::Key_Left:
4278  pos = ctrl ? old_pos.previousWordPosition() : old_pos.previousCharacterPosition();
4279  break;
4280 
4281  case Qt::Key_Right:
4282  pos = ctrl ? old_pos.nextWordPosition() : old_pos.nextCharacterPosition();
4283  break;
4284 
4285  case Qt::Key_PageDown:
4286 // moveCaretNextPage(); ###
4287  break;
4288 
4289  case Qt::Key_PageUp:
4290 // moveCaretPrevPage(); ###
4291  break;
4292 
4293  case Qt::Key_Home:
4294  if (ctrl)
4295  /*moveCaretToDocumentBoundary(false)*/; // ###
4296  else
4297  pos = positionOfLineBegin(old_pos);
4298  break;
4299 
4300  case Qt::Key_End:
4301  if (ctrl)
4302  /*moveCaretToDocumentBoundary(true)*/; // ###
4303  else
4304  pos = positionOfLineEnd(old_pos);
4305  break;
4306 
4307  default:
4308  handled = false;
4309 
4310  }/*end switch*/
4311 
4312  if (pos != old_pos) {
4313  m_part->clearCaretRectIfNeeded();
4314 
4315  caret.moveTo(shift ? caret.nonCaretPos() : pos, pos);
4316  int old_x = caret.xPosForVerticalArrowNavigation(Selection::CARETPOS);
4317 
4318  m_part->selectionLayoutChanged();
4319 
4320  // restore old x-position to prevent recalculation
4321  if (!recalcXPos)
4322  m_part->d->editor_context.m_xPosForVerticalArrowNavigation = old_x;
4323 
4324  m_part->emitCaretPositionChanged(pos);
4325  // ### check when to emit it
4326  m_part->notifySelectionChanged();
4327 
4328  }
4329 
4330  if (handled) _ke->accept();
4331  return handled;
4332 }
4333 
4334 #undef DEBUG_CARETMODE
QHideEvent
khtml::KHTMLWidget::m_kwp
KHTMLWidgetPrivate * m_kwp
Definition: khtmlview.h:75
QObject::child
QObject * child(const char *objName, const char *inheritsClass, bool recursiveSearch) const
QPalette::setBrush
void setBrush(ColorRole role, const QBrush &brush)
khtml::MousePressEvent
Definition: khtml_events.h:63
kdialog.h
QTransform
i18n
QString i18n(const char *text)
KHTMLView::smoothScrollingMode
SmoothScrollingMode smoothScrollingMode() const
Retrieve the current smooth scrolling mode.
Definition: khtmlview.cpp:1103
KIconLoader::DefaultState
khtml::EditorContext
Contextual information about the caret and the built-in editor.
Definition: editing_p.h:38
KHTMLSettings::changeCursor
bool changeCursor() const
Definition: khtml_settings.cpp:327
KHTMLView::updateContents
void updateContents(const QRect &r)
Requests an update of the content area.
Definition: khtmlview.cpp:784
KHTMLView::SmoothScrollingMode
SmoothScrollingMode
Smooth Scrolling Mode enumeration.
Definition: khtmlview.h:305
QWidget::close
bool close()
QEvent
QResizeEvent
QWidget
KHTMLView::setSmoothScrollingModeDefault
void setSmoothScrollingModeDefault(SmoothScrollingMode m)
Definition: khtmlview.cpp:1093
KHTMLSettings::fallbackAccessKeysAssignments
QList< QPair< QString, QChar > > fallbackAccessKeysAssignments() const
Definition: khtml_settings.cpp:1178
QWidget::underMouse
bool underMouse() const
KHTMLView::cleared
void cleared()
QKeyEvent::modifiers
Qt::KeyboardModifiers modifiers() const
QApplication::isRightToLeft
bool isRightToLeft()
QScrollBar::sizeHint
virtual QSize sizeHint() const
QPainter::setViewport
void setViewport(const QRect &rectangle)
QScrollArea::setWidget
void setWidget(QWidget *widget)
QRect::size
QSize size() const
QEvent::type
Type type() const
QApplication::doubleClickInterval
int doubleClickInterval()
QWidget::palette
const QPalette & palette() const
QString::toUpper
QString toUpper() const
QLinkedList::erase
iterator erase(iterator pos)
sSmoothScrollMinStaticPixels
static const int sSmoothScrollMinStaticPixels
Definition: khtmlview.cpp:126
QDialog::reject
virtual void reject()
DOM::DOMString::length
uint length() const
Definition: dom_string.cpp:185
KHTMLPartPrivate::m_bOpenMiddleClick
bool m_bOpenMiddleClick
Definition: khtmlpart_p.h:254
KHTMLView::mouseDoubleClickEvent
virtual void mouseDoubleClickEvent(QMouseEvent *)
Definition: khtmlview.cpp:1242
QSize::width
int width() const
KHTMLPart::urlCursor
QCursor urlCursor() const
Returns the cursor which is used when the cursor is on a link.
Definition: khtml_part.cpp:2788
QPointer::data
T * data() const
khtml::EditorContext::m_selection
DOM::Selection m_selection
Definition: editing_p.h:44
buildLabels
static QMap< NodeImpl *, QString > buildLabels(NodeImpl *start)
Definition: khtmlview.cpp:2735
KHTMLSettings::isFormCompletionEnabled
bool isFormCompletionEnabled() const
Definition: khtml_settings.cpp:1084
DOM::Node
The Node interface is the primary datatype for the entire Document Object Model.
Definition: dom_node.h:270
QScrollArea::ensureVisible
void ensureVisible(int x, int y, int xmargin, int ymargin)
QPixmap::width
int width() const
QWheelEvent::x
int x() const
QWheelEvent::y
int y() const
QPainter::end
bool end()
QMap::contains
bool contains(const Key &key) const
QWidget::setCursor
void setCursor(const QCursor &)
kdebug.h
khtml::ChildFrame
Definition: khtml_childframe_p.h:40
QPainter::fillRect
void fillRect(const QRectF &rectangle, const QBrush &brush)
KHTMLView::setSmoothScrollingMode
void setSmoothScrollingMode(SmoothScrollingMode m)
Set the smooth scrolling mode.
Definition: khtmlview.cpp:1085
QAbstractEventDispatcher::instance
QAbstractEventDispatcher * instance(QThread *thread)
getElementText
static QString getElementText(NodeImpl *start, bool after)
Definition: khtmlview.cpp:2684
KHTMLSettings::maxFormCompletionItems
int maxFormCompletionItems() const
Definition: khtml_settings.cpp:1089
QRegion::translate
void translate(int dx, int dy)
QVector::append
void append(const T &value)
QPixmap::fill
void fill(const QColor &color)
KHTMLPartPrivate::editor_context
khtml::EditorContext editor_context
Definition: khtmlpart_p.h:371
QWidget::keyReleaseEvent
virtual void keyReleaseEvent(QKeyEvent *event)
QVector::begin
iterator begin()
QRect::right
int right() const
QPainter::window
QRect window() const
QAbstractSlider::setRange
void setRange(int min, int max)
khtml::MouseMoveEvent
Definition: khtml_events.h:100
kglobalsettings.h
assert
#define assert(x)
Definition: editor.cpp:43
QWidget::windowModality
windowModality
QPrinter
sLayoutAttemptDelay
static const int sLayoutAttemptDelay
Definition: khtmlview.cpp:115
QPaintDevice
QWidget::setFocusPolicy
void setFocusPolicy(Qt::FocusPolicy policy)
khtml_part.h
QChar
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
timeout
int timeout
QScrollArea::widget
QWidget * widget() const
QWheelEvent::buttons
Qt::MouseButtons buttons() const
QKeyEvent::count
int count() const
d
#define d
Definition: khtmlfind.cpp:42
QString::prepend
QString & prepend(QChar ch)
QHashIterator::hasNext
bool hasNext() const
positionOfLineEnd
static DOM::Position positionOfLineEnd(const DOM::Position &pos)
Definition: khtmlview.cpp:4247
QAbstractScrollArea
QLinkedList::begin
iterator begin()
QX11Info::display
Display * display()
KParts::ReadOnlyPart::completed
void completed()
QFont
QWidget::style
QStyle * style() const
label
QString label(StandardShortcut id)
KHTMLView::contentsY
int contentsY() const
Returns the y coordinate of the contents area point that is currently located at the top left in the ...
Definition: khtmlview.cpp:695
QPainter::scale
void scale(qreal sx, qreal sy)
QMouseEvent::x
int x() const
QMouseEvent::y
int y() const
kconfig.h
KHTMLView::focusOutEvent
virtual void focusOutEvent(QFocusEvent *)
Definition: khtmlview.cpp:3739
KHTMLView::contentsToViewport
QPoint contentsToViewport(const QPoint &p) const
Returns a point translated to viewport coordinates.
Definition: khtmlview.cpp:747
QMap
QObject::children
const QObjectList & children() const
KLocale::ShortDate
QPointer< QWidget >
QWheelEvent
KHTMLView::addChild
void addChild(QWidget *child, int dx, int dy)
Definition: khtmlview.cpp:3952
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
QString::simplified
QString simplified() const
KHTMLPart::frameExists
bool frameExists(const QString &frameName)
Returns whether a frame with the specified name is exists or not.
Definition: khtml_part.cpp:5314
QWidget::y
y
KHTMLPart
This class is khtml's main class.
Definition: khtml_part.h:206
QRect::translate
void translate(int dx, int dy)
QWidget::isVisible
bool isVisible() const
QRect::intersects
bool intersects(const QRect &rectangle) const
QPainter::save
void save()
findImageMapRect
static bool findImageMapRect(HTMLImageElementImpl *img, const QPoint &scrollOfs, const QPoint &p, QRect &r, QString &s)
calculates the client-side image map rectangle for the given image element
Definition: khtmlview.cpp:451
QRect::unite
QRect unite(const QRect &rectangle) const
KHTMLView::SSMEnabled
Definition: khtmlview.h:305
QScrollBar
QHelpEvent::pos
const QPoint & pos() const
QWidget::setAttribute
void setAttribute(Qt::WidgetAttribute attribute, bool on)
QWidget::visibleRect
QRect visibleRect() const
DOM::DOMString::string
QString string() const
Definition: dom_string.cpp:236
QAbstractScrollArea::wheelEvent
virtual void wheelEvent(QWheelEvent *e)
QAbstractScrollArea::viewport
QWidget * viewport() const
KHTMLView
Renders and displays HTML in a QScrollArea.
Definition: khtmlview.h:92
QWeakPointer::data
T * data() const
QList::erase
iterator erase(iterator pos)
QRect::height
int height() const
QBrush
QRegion::boundingRect
QRect boundingRect() const
QRect::x
int x() const
QRect::y
int y() const
kiconloader.h
double
QAbstractSlider::setPageStep
void setPageStep(int)
QWidget::icon
const QPixmap * icon() const
QWidget::hasFocus
bool hasFocus() const
QPoint
KDialog
QPainter::setClipRegion
void setClipRegion(const QRegion &region, Qt::ClipOperation operation)
QMouseEvent
QMouseEvent::buttons
Qt::MouseButtons buttons() const
KHTMLView::eventFilter
virtual bool eventFilter(QObject *, QEvent *)
Definition: khtmlview.cpp:2024
QKeyEvent::isAutoRepeat
bool isAutoRepeat() const
QWheelEvent::pos
const QPoint & pos() const
KHTMLGlobal::defaultHTMLSettings
static KHTMLSettings * defaultHTMLSettings()
Definition: khtml_global.cpp:237
sSmoothScrollTick
static const int sSmoothScrollTick
Definition: khtmlview.cpp:125
QFrame::setFrameStyle
void setFrameStyle(int style)
QPixmap::createMaskFromColor
QBitmap createMaskFromColor(const QColor &maskColor) const
QAbstractScrollArea::dragEnterEvent
virtual void dragEnterEvent(QDragEnterEvent *event)
KdePrint::createPrintDialog
QPrintDialog * createPrintDialog(QPrinter *printer, PageSelectPolicy pageSelectPolicy, const QList< QWidget * > &customTabs, QWidget *parent=0)
QFrame::setLineWidth
void setLineWidth(int)
KHTMLView::setContentsPos
void setContentsPos(int x, int y)
Place the contents area point x/y at the top left of the viewport.
Definition: khtmlview.cpp:732
KHTMLView::repaintAccessKeys
void repaintAccessKeys()
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
klocale.h
QWidget::adjustSize
void adjustSize()
QWeakPointer::isNull
bool isNull() const
QToolTip::showText
void showText(const QPoint &pos, const QString &text, QWidget *w)
QTime
khtml::MouseReleaseEvent
Definition: khtml_events.h:115
khtml::EditorContext::m_beganSelectingText
bool m_beganSelectingText
Definition: editing_p.h:52
QWidget::focusOutEvent
virtual void focusOutEvent(QFocusEvent *event)
QWidget::setParent
void setParent(QWidget *parent)
ref
void ref()
QLinkedList::end
iterator end()
QWidget::update
void update()
positionOfLineBegin
static DOM::Position positionOfLineBegin(const DOM::Position &pos)
Definition: khtmlview.cpp:4242
KHTMLView::focusNextPrevChild
virtual bool focusNextPrevChild(bool next)
Definition: khtmlview.cpp:1868
QPoint::x
int x() const
QPoint::y
int y() const
KGlobal::config
KSharedConfigPtr config()
QString::isNull
bool isNull() const
QPrinter::paperRect
QRect paperRect() const
editor.h
QPainter::viewTransformEnabled
bool viewTransformEnabled() const
KHTMLView::closeEvent
virtual void closeEvent(QCloseEvent *)
Definition: khtmlview.cpp:1062
QPaintDevice::width
int width() const
QWidget::width
width
knotification.h
khtml_printsettings.h
QBitmap
QPainter::resetTransform
void resetTransform()
QCloseEvent
KHTMLPart::view
KHTMLView * view() const
Returns a pointer to the HTML document's view.
Definition: khtml_part.cpp:1059
KHTMLView::mousePressEvent
virtual void mousePressEvent(QMouseEvent *)
Definition: khtmlview.cpp:1113
KHTMLView::part
KHTMLPart * part() const
Returns a pointer to the KHTMLPart that is rendering the page.
Definition: khtmlview.h:135
kcursor.h
KHTMLView::scrollContentsBy
virtual void scrollContentsBy(int dx, int dy)
Definition: khtmlview.cpp:3752
QWidget::size
size
QPaintEvent::rect
const QRect & rect() const
QPainter::setWindow
void setWindow(const QRect &rectangle)
QLinkedList
Qt::convertFromPlainText
QString convertFromPlainText(const QString &plain, WhiteSpaceMode mode)
QTimerEvent
QStyleOption
QFocusEvent::reason
Qt::FocusReason reason() const
KHTMLView::visibleWidth
int visibleWidth() const
Returns the width of the viewport.
Definition: khtmlview.cpp:700
KHTMLPart::frames
QList< KParts::ReadOnlyPart * > frames() const
Definition: khtml_part.cpp:6046
KHTMLView::visibleHeight
int visibleHeight() const
Returns the height of the viewport.
Definition: khtmlview.cpp:716
QRect
QPainter::setFont
void setFont(const QFont &font)
QTime::elapsed
int elapsed() const
KHTMLView::layout
void layout()
ensure the display is up to date
Definition: khtmlview.cpp:954
KIconLoader::loadIcon
QPixmap loadIcon(const QString &name, KIconLoader::Group group, int size=0, int state=KIconLoader::DefaultState, const QStringList &overlays=QStringList(), QString *path_store=0L, bool canReturnNull=false) const
QWidget::testAttribute
bool testAttribute(Qt::WidgetAttribute attribute) const
QWidget::setEnabled
void setEnabled(bool)
QWidget::showEvent
virtual void showEvent(QShowEvent *event)
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
QMouseEvent::globalPos
const QPoint & globalPos() const
KHTMLView::focusInEvent
virtual void focusInEvent(QFocusEvent *)
Definition: khtmlview.cpp:3728
KHTMLPart::setCaretVisible
void setCaretVisible(bool show)
Sets the visibility of the caret.
Definition: khtml_part.cpp:2952
QChar::isSpace
bool isSpace() const
KdePrint::SystemSelectsPages
QEvent::isAccepted
bool isAccepted() const
QEvent::ignore
void ignore()
KHTMLView::SSMWhenEfficient
Definition: khtmlview.h:305
sParsingLayoutsInterval
static const int sParsingLayoutsInterval
Definition: khtmlview.cpp:114
QToolTip::isVisible
bool isVisible()
QObject::installEventFilter
void installEventFilter(QObject *filterObj)
QTimer
QPrinter::setCreator
void setCreator(const QString &creator)
QWidget::x
x
QPainter::boundingRect
QRectF boundingRect(const QRectF &rectangle, int flags, const QString &text)
KHTMLView::setVerticalScrollBarPolicy
virtual void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy policy)
Sets vertical scrollbar mode.
Definition: khtmlview.cpp:3367
QAbstractScrollArea::viewportEvent
virtual bool viewportEvent(QEvent *event)
KIconLoader::Small
QHash< void *, QWidget * >
khtml::KHTMLWidget
Definition: khtmlview.h:70
QRect::top
int top() const
QWheelEvent::orientation
Qt::Orientation orientation() const
QPainter::clipRegion
QRegion clipRegion() const
KHTMLView::zoomView
void zoomView(int)
QContextMenuEvent
QShowEvent
QObject
QPainter::setPen
void setPen(const QColor &color)
QPainter::setWorldTransform
void setWorldTransform(const QTransform &matrix, bool combine)
QHelpEvent::globalPos
const QPoint & globalPos() const
QWidget::setFocus
void setFocus()
QPainter::drawEllipse
void drawEllipse(const QRectF &rectangle)
QWidget::focusNextPrevChild
virtual bool focusNextPrevChild(bool next)
QWidget::hideEvent
virtual void hideEvent(QHideEvent *event)
KHTMLView::contentsHeight
int contentsHeight() const
Returns the contents area's height.
Definition: khtmlview.cpp:676
QRect::left
int left() const
QMouseEvent::button
Qt::MouseButton button() const
khtml::EditorContext::m_xPosForVerticalArrowNavigation
int m_xPosForVerticalArrowNavigation
Definition: editing_p.h:59
QDropEvent
QAbstractScrollArea::setHorizontalScrollBarPolicy
void setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy)
QScrollArea::event
virtual bool event(QEvent *e)
QPainter::drawPixmap
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
KHTMLView::dragEnterEvent
virtual void dragEnterEvent(QDragEnterEvent *)
Definition: khtmlview.cpp:3716
QList::isEmpty
bool isEmpty() const
QPainter
QObject::objectName
objectName
QWidget::focusInEvent
virtual void focusInEvent(QFocusEvent *event)
QHashIterator
QWidget::setFocusProxy
void setFocusProxy(QWidget *w)
QRect::setWidth
void setWidth(int width)
QString::isEmpty
bool isEmpty() const
QList::removeAll
int removeAll(const T &value)
QString::trimmed
QString trimmed() const
KHTMLView::hideEvent
virtual void hideEvent(QHideEvent *)
Definition: khtmlview.cpp:641
QCoreApplication::sendEvent
bool sendEvent(QObject *receiver, QEvent *event)
if
if(!yymsg) yymsg
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
QKeyEvent::text
QString text() const
KHTMLView::~KHTMLView
virtual ~KHTMLView()
Definition: khtmlview.cpp:563
QPainter::device
QPaintDevice * device() const
QWidget::move
void move(int x, int y)
QPainter::drawText
void drawText(const QPointF &position, const QString &text)
QPrinter::setDocName
void setDocName(const QString &name)
DOM::DOMString
This class implements the basic string we use in the DOM.
Definition: dom_string.h:43
QRect::translated
QRect translated(int dx, int dy) const
khtml::MouseDoubleClickEvent
Definition: khtml_events.h:79
KHTMLView::keyPressEvent
void keyPressEvent(QKeyEvent *_ke)
Definition: khtmlview.cpp:1676
QList::front
T & front()
KStringHandler::csqueeze
QString csqueeze(const QString &str, int maxlen=40)
handleWidget
static void handleWidget(QWidget *w, KHTMLView *view, bool recurse=true)
Definition: khtmlview.cpp:1938
QString
QList
QWidget::hide
void hide()
QAbstractSlider::minimum
minimum
QMap::end
iterator end()
QColor
sFirstLayoutDelay
static const int sFirstLayoutDelay
Definition: khtmlview.cpp:113
QScrollArea::eventFilter
virtual bool eventFilter(QObject *o, QEvent *e)
QAbstractScrollArea::verticalScrollBar
QScrollBar * verticalScrollBar() const
KHTMLView::hideAccessKeys
void hideAccessKeys()
sLayoutAttemptIncrement
static const int sLayoutAttemptIncrement
Definition: khtmlview.cpp:121
khtml_events.h
QPainter::worldTransform
const QTransform & worldTransform() const
QMap::begin
iterator begin()
QStringList
QAbstractScrollArea::event
virtual bool event(QEvent *event)
KHTMLView::paintEvent
virtual void paintEvent(QPaintEvent *)
Definition: khtmlview.cpp:869
QWidget::isWindow
bool isWindow() const
QWidget::rect
QRect rect() const
KHTMLGlobal::iconLoader
static KIconLoader * iconLoader()
Definition: khtml_global.cpp:227
QPair
QPixmap
KHTMLView::setMarginWidth
void setMarginWidth(int x)
Sets a margin in x direction.
Definition: khtmlview.cpp:942
QWidget::setAcceptDrops
void setAcceptDrops(bool on)
QPaintDevice::logicalDpiY
int logicalDpiY() const
QInputEvent::modifiers
Qt::KeyboardModifiers modifiers() const
QChildEvent
sMaxMissedDeadlines
static const int sMaxMissedDeadlines
Definition: khtmlview.cpp:128
KHTMLView::scrollBy
void scrollBy(int x, int y)
Scrolls the content area by a given amount.
Definition: khtmlview.cpp:739
QChar::isNull
bool isNull() const
KHTMLView::KHTMLViewPrivate
friend class KHTMLViewPrivate
Definition: khtmlview.h:517
QList::end
iterator end()
QString::toLower
QString toLower() const
kstandardshortcut.h
QKeyEvent::key
int key() const
sParsingLayoutsIncrement
static const int sParsingLayoutsIncrement
Definition: khtmlview.cpp:122
QEvent::accept
void accept()
QPoint::manhattanLength
int manhattanLength() const
KHTMLSettings::accessKeysEnabled
bool accessKeysEnabled() const
Definition: khtml_settings.cpp:818
QHashIterator::next
Item next()
QSize
KHTMLPartPrivate::m_parsetime
QTime m_parsetime
Definition: khtmlpart_p.h:313
QPrinter::setFullPage
void setFullPage(bool fp)
QPixmap::height
int height() const
fixx11h.h
QCoreApplication::flush
void flush()
KHTMLView::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *)
Definition: khtmlview.cpp:1301
QAbstractSlider::setValue
void setValue(int)
KHTMLView::timerEvent
void timerEvent(QTimerEvent *)
Definition: khtmlview.cpp:3965
QRect::isEmpty
bool isEmpty() const
QList::contains
bool contains(const T &value) const
QToolTip::hideText
void hideText()
QRect::isValid
bool isValid() const
KHTMLView::viewportToContents
QPoint viewportToContents(const QPoint &p) const
Returns a point translated to contents area coordinates.
Definition: khtmlview.cpp:760
KHTMLView::resizeEvent
virtual void resizeEvent(QResizeEvent *event)
Definition: khtmlview.cpp:837
kstringhandler.h
khtmlview.h
QPrinter::newPage
bool newPage()
QWheelEvent::delta
int delta() const
QWidget::repaint
void repaint()
QPainter::viewport
QRect viewport() const
KGlobal::locale
KLocale * locale()
QPainter::restore
void restore()
KHTMLView::setZoomLevel
void setZoomLevel(int percent)
Apply a zoom level to the content area.
Definition: khtmlview.cpp:1068
KConfigGroup
QRect::isNull
bool isNull() const
QKeyEvent
QWidget::windowFlags
windowFlags
QObject::startTimer
int startTimer(int interval)
KConfig
KHTMLView::setHorizontalScrollBarPolicy
virtual void setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy policy)
Sets horizontal scrollbar mode.
Definition: khtmlview.cpp:3377
sSmoothScrollTime
static const int sSmoothScrollTime
Definition: khtmlview.cpp:124
kdeprintdialog.h
QRect::width
int width() const
QPainter::setClipRect
void setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
QCursor::pos
QPoint pos()
QVector
Definition: khtmlview.h:36
QDragEnterEvent
KHTMLView::event
virtual bool event(QEvent *event)
Definition: khtmlview.cpp:481
QMouseEvent::globalX
int globalX() const
QMouseEvent::globalY
int globalY() const
sWayTooMany
static const int sWayTooMany
Definition: khtmlview.cpp:129
QWidget::mapTo
QPoint mapTo(QWidget *parent, const QPoint &pos) const
QApplication::style
QStyle * style()
QChar::toUpper
QChar toUpper() const
QRect::setX
void setX(int x)
QRect::setY
void setY(int y)
QSize::expandedTo
QSize expandedTo(const QSize &otherSize) const
KHTMLView::widgetEvent
virtual bool widgetEvent(QEvent *)
Definition: khtmlview.cpp:2195
KStandardDirs::locateLocal
static QString locateLocal(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
QCoreApplication::sendPostedEvents
void sendPostedEvents()
KHTMLPart::isEditable
bool isEditable() const
Returns true if the document is editable, false otherwise.
Definition: khtml_part.cpp:2904
QRectF
QToolTip::palette
QPalette palette()
QPainter::fontMetrics
QFontMetrics fontMetrics() const
QRect::setHeight
void setHeight(int height)
kstandarddirs.h
QCursor::handle
HCURSOR_or_HANDLE handle() const
KHTMLView::finishedLayout
void finishedLayout()
This signal is used for internal layouting.
QWidget::parentWidget
QWidget * parentWidget() const
QDate::currentDate
QDate currentDate()
QWidget::mapFromGlobal
QPoint mapFromGlobal(const QPoint &pos) const
KHTMLView::viewportEvent
virtual bool viewportEvent(QEvent *e)
Definition: khtmlview.cpp:1979
QWidget::QWidget
QWidget(QWidget *parent, QFlags< Qt::WindowType > f)
QPainter::setWorldMatrixEnabled
void setWorldMatrixEnabled(bool enable)
KHTMLView::contentsX
int contentsX() const
Returns the x coordinate of the contents area point that is currently located at the top left in the ...
Definition: khtmlview.cpp:690
QList::ConstIterator
typedef ConstIterator
QRegion::rects
QVector< QRect > rects() const
QSize::height
int height() const
QRect::adjust
void adjust(int dx1, int dy1, int dx2, int dy2)
QBitmap::clear
void clear()
QPainter::worldMatrixEnabled
bool worldMatrixEnabled() const
QRect::bottom
int bottom() const
QRect::topLeft
QPoint topLeft() const
KHTMLPart::isCaretMode
bool isCaretMode() const
Returns whether caret mode is on/off.
Definition: khtml_part.cpp:2884
QString::length
int length() const
KHTMLView::setMarginHeight
void setMarginHeight(int y)
Definition: khtmlview.cpp:948
QPainter::translate
void translate(const QPointF &offset)
QWidget::setMouseTracking
void setMouseTracking(bool enable)
QTimerEvent::timerId
int timerId() const
khtml::ChildFrame::m_partContainerElement
QWeakPointer< DOM::HTMLPartContainerElementImpl > m_partContainerElement
Definition: khtml_childframe_p.h:49
KDE_VERSION_MAJOR
#define KDE_VERSION_MAJOR
KHTMLPart::fontScaleFactor
int fontScaleFactor() const
Returns the current font scale factor.
Definition: khtml_part.cpp:5886
QStyle::drawPrimitive
virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const =0
kWarning
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
QRect::intersect
QRect intersect(const QRect &rectangle) const
QPrinter::pageRect
QRect pageRect() const
QRegion::isEmpty
bool isEmpty() const
KHTMLView::doAutoScroll
void doAutoScroll()
Definition: khtmlview.cpp:1887
QDialog
QAbstractScrollArea::horizontalScrollBar
QScrollBar * horizontalScrollBar() const
KHTMLView::print
void print(bool quick=false)
Prints the HTML document.
Definition: khtmlview.cpp:3027
QAbstractScrollArea::maximumViewportSize
QSize maximumViewportSize() const
KLocale::formatDate
QString formatDate(const QDate &date, DateFormat format=LongDate) const
KHTMLView::wheelEvent
virtual void wheelEvent(QWheelEvent *)
Definition: khtmlview.cpp:3636
QStringList::indexOf
int indexOf(const QRegExp &rx, int from) const
QList::prepend
void prepend(const T &value)
QWidget::setAutoFillBackground
void setAutoFillBackground(bool enabled)
QWidget::show
void show()
QLineEdit
QWidget::scroll
void scroll(int dx, int dy)
KHTMLView::contentsWidth
int contentsWidth() const
Returns the contents area's width.
Definition: khtmlview.cpp:671
reset
KGuiItem reset()
QWidget::closeEvent
virtual void closeEvent(QCloseEvent *event)
QMouseEvent::pos
const QPoint & pos() const
khtmlpart_p.h
QPainter::setViewTransformEnabled
void setViewTransformEnabled(bool enable)
KDE_VERSION_MINOR
#define KDE_VERSION_MINOR
QPaintEvent
QAbstractScrollArea::dropEvent
virtual void dropEvent(QDropEvent *event)
QPaintDevice::height
int height() const
QHashIterator::value
const T & value() const
KHTMLView::SSMDisabled
Definition: khtmlview.h:305
KHTMLPart::nodeActivated
void nodeActivated(const DOM::Node &)
This signal is emitted when an element retrieves the keyboard focus.
QObject::isWidgetType
bool isWidgetType() const
KHTMLPrintSettings
Definition: khtml_printsettings.h:27
QScrollArea
KHTMLView::clear
void clear()
Definition: khtmlview.cpp:621
KHTMLView::repaintContents
void repaintContents(const QRect &r)
Requests an immediate repaint of the content area.
Definition: khtmlview.cpp:800
QCoreApplication::postEvent
void postEvent(QObject *receiver, QEvent *event)
QAbstractSlider::maximum
maximum
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KHTMLView::dropEvent
virtual void dropEvent(QDropEvent *)
Definition: khtmlview.cpp:3722
DOM::Node::handle
NodeImpl * handle() const
Definition: dom_node.h:925
QLabel
QObject::parent
QObject * parent() const
QVector::size
int size() const
QTextEdit
QHelpEvent
QPainter::begin
bool begin(QPaintDevice *device)
khtml_settings.h
QCursor
QPixmap::rect
QRect rect() const
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QWidget::event
virtual bool event(QEvent *event)
QAbstractScrollArea::setVerticalScrollBarPolicy
void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy)
QVector::end
iterator end()
KConfigGroup::readEntry
T readEntry(const QString &key, const T &aDefault) const
QList::removeOne
bool removeOne(const T &value)
KHTMLView::keyReleaseEvent
void keyReleaseEvent(QKeyEvent *_ke)
Definition: khtmlview.cpp:1826
QFocusEvent
KHTMLPartPrivate::m_bMousePressed
bool m_bMousePressed
Definition: khtmlpart_p.h:367
QFrame::event
virtual bool event(QEvent *e)
QObject::killTimer
void killTimer(int id)
QRect::getRect
void getRect(int *x, int *y, int *width, int *height) const
QLabel::setMargin
void setMargin(int)
QChar::isNumber
bool isNumber() const
QList::begin
iterator begin()
KHTMLPart::settings
const KHTMLSettings * settings() const
Definition: khtml_part.cpp:2508
KHTMLView::showEvent
virtual void showEvent(QShowEvent *)
Definition: khtmlview.cpp:646
positionOfLineBoundary
static DOM::Position positionOfLineBoundary(const DOM::Position &pos, bool toEnd)
Definition: khtmlview.cpp:4235
KHTMLView::KHTMLView
KHTMLView(KHTMLPart *part, QWidget *parent)
Constructs a KHTMLView.
Definition: khtmlview.cpp:549
QFontMetrics::lineSpacing
int lineSpacing() const
QPalette
targetOpensNewWindow
static bool targetOpensNewWindow(KHTMLPart *part, QString target)
Definition: khtmlview.cpp:1285
KHTMLView::zoomLevel
int zoomLevel() const
Retrieve the current zoom level.
Definition: khtmlview.cpp:1080
QWidget::height
height
KHTMLView::resizeContents
virtual void resizeContents(int w, int h)
Resize the contents area.
Definition: khtmlview.cpp:681
KHTMLView::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *)
Definition: khtmlview.cpp:1545
QWidget::mask
QRegion mask() const
KHTMLView::displayAccessKeys
void displayAccessKeys()
Display all accesskeys in small tooltips.
Definition: khtmlview.cpp:2502
khtml::DrawContentsEvent
Definition: khtml_events.h:130
QRegion
kconfiggroup.h
QLinkedList::append
void append(const T &value)
KHTMLPart::parentPart
KHTMLPart * parentPart()
Returns a pointer to the parent KHTMLPart if the part is a frame in an HTML frameset.
Definition: khtml_part.cpp:5356
QStack< QRegion >
QApplication::startDragDistance
int startDragDistance()
QCursor::shape
Qt::CursorShape shape() const
QAbstractEventDispatcher::unregisterTimers
virtual bool unregisterTimers(QObject *object)=0
KDE_VERSION_RELEASE
#define KDE_VERSION_RELEASE
KParts::ReadOnlyPart
setInPaintEventFlag
static void setInPaintEventFlag(QWidget *w, bool b=true, bool recurse=true)
Definition: khtmlview.cpp:2003
QTimer::singleShot
singleShot
KHTMLView::slotPaletteChanged
void slotPaletteChanged()
Definition: khtmlview.cpp:3215
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:26:19 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal