📄 khtmlview.cpp
字号:
QScrollView::hideEvent(e);
}
void KHTMLView::showEvent(QShowEvent* e)
{
// viewport()->setBackgroundMode(NoBackground);
QScrollView::showEvent(e);
}
void KHTMLView::resizeEvent (QResizeEvent* e)
{
QScrollView::resizeEvent(e);
#if !APPLE_CHANGES
int w = visibleWidth();
int h = visibleHeight();
layout();
// this is to make sure we get the right width even if the scrolbar has dissappeared
// due to the size change.
if(visibleHeight() != h || visibleWidth() != w)
layout();
#endif
if ( m_part && m_part->xmlDocImpl() )
m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false );
KApplication::sendPostedEvents(viewport(), QEvent::Paint);
}
#if APPLE_CHANGES
void KHTMLView::initScrollBars()
{
if (!d->needToInitScrollBars)
return;
d->needToInitScrollBars = false;
setScrollBarsMode(hScrollBarMode());
}
#endif
#if !APPLE_CHANGES
// this is to get rid of a compiler virtual overload mismatch warning. do not remove
void KHTMLView::drawContents( QPainter*)
{
}
void KHTMLView::drawContents( QPainter *p, int ex, int ey, int ew, int eh )
{
//kdDebug( 6000 ) << "drawContents x=" << ex << ",y=" << ey << ",w=" << ew << ",h=" << eh << endl;
if(!m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
p->fillRect(ex, ey, ew, eh, palette().normal().brush(QColorGroup::Base));
return;
}
if ( d->paintBuffer->width() < visibleWidth() )
d->paintBuffer->resize(visibleWidth(),PAINT_BUFFER_HEIGHT);
int py=0;
while (py < eh) {
int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;
d->tp->begin(d->paintBuffer);
d->tp->translate(-ex, -ey-py);
d->tp->fillRect(ex, ey+py, ew, ph, palette().normal().brush(QColorGroup::Base));
m_part->xmlDocImpl()->renderer()->print(d->tp, ex, ey+py, ew, ph, 0, 0);
#ifdef BOX_DEBUG
if (m_part->xmlDocImpl()->focusNode())
{
d->tp->setBrush(Qt::NoBrush);
d->tp->drawRect(m_part->xmlDocImpl()->focusNode()->getRect());
}
#endif
d->tp->end();
p->drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph);
py += PAINT_BUFFER_HEIGHT;
}
// EDIT FIXME: KDE needs to draw the caret here.
khtml::DrawContentsEvent event( p, ex, ey, ew, eh );
QApplication::sendEvent( m_part, &event );
}
#endif // !APPLE_CHANGES
void KHTMLView::setMarginWidth(int w)
{
// make it update the rendering area when set
_marginWidth = w;
}
void KHTMLView::setMarginHeight(int h)
{
// make it update the rendering area when set
_marginHeight = h;
}
void KHTMLView::adjustViewSize()
{
if( m_part->xmlDocImpl() ) {
DOM::DocumentImpl *document = m_part->xmlDocImpl();
khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas *>(document->renderer());
if ( !root )
return;
int docw = root->docWidth();
int doch = root->docHeight();
resizeContents(docw, doch);
}
}
void KHTMLView::applyBodyScrollQuirk(khtml::RenderObject* o, ScrollBarMode& hMode, ScrollBarMode& vMode)
{
// Handle the overflow:hidden/scroll quirk for the body elements. WinIE treats
// overflow:hidden and overflow:scroll on <body> as applying to the document's
// scrollbars. The CSS2.1 draft has even added a sentence, "HTML UAs may apply overflow
// specified on the body or HTML elements to the viewport." Since WinIE and Mozilla both
// do it, we will do it too for <body> elements.
switch(o->style()->overflow()) {
case OHIDDEN:
hMode = vMode = AlwaysOff;
break;
case OSCROLL:
hMode = vMode = AlwaysOn;
break;
case OAUTO:
hMode = vMode = Auto;
break;
default:
// Don't set it at all.
;
}
}
bool KHTMLView::inLayout() const
{
return d->layoutSuppressed;
}
int KHTMLView::layoutCount() const
{
return d->layoutCount;
}
bool KHTMLView::needsFullRepaint() const
{
return d->doFullRepaint;
}
void KHTMLView::addRepaintInfo(RenderObject* o, const QRect& r)
{
if (!d->repaintRects) {
d->repaintRects = new QPtrList<RenderObject::RepaintInfo>;
d->repaintRects->setAutoDelete(true);
}
d->repaintRects->append(new RenderObject::RepaintInfo(o, r));
}
void KHTMLView::layout()
{
if (d->layoutSuppressed)
return;
d->layoutSchedulingEnabled=false;
killTimer(d->layoutTimerId);
d->layoutTimerId = 0;
d->delayedLayout = false;
if (!m_part) {
// FIXME: Do we need to set _width here?
// FIXME: Should we set _height here too?
_width = visibleWidth();
return;
}
DOM::DocumentImpl* document = m_part->xmlDocImpl();
if (!document) {
// FIXME: Should we set _height here too?
_width = visibleWidth();
return;
}
// Always ensure our style info is up-to-date. This can happen in situations where
// the layout beats any sort of style recalc update that needs to occur.
if (document->hasChangedChild())
document->recalcStyle();
khtml::RenderCanvas* root = static_cast<khtml::RenderCanvas*>(document->renderer());
if (!root) {
// FIXME: Do we need to set _width or _height here?
return;
}
ScrollBarMode hMode = d->hmode;
ScrollBarMode vMode = d->vmode;
if (document->isHTMLDocument()) {
NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
if (body && body->renderer()) {
if (body->id() == ID_FRAMESET) {
body->renderer()->setNeedsLayout(true);
vMode = AlwaysOff;
hMode = AlwaysOff;
}
else if (body->id() == ID_BODY)
applyBodyScrollQuirk(body->renderer(), hMode, vMode); // Only applies to HTML UAs, not to XML/XHTML UAs
}
}
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
if (d->firstLayout && !document->ownerElement())
printf("Elapsed time before first layout: %d\n", document->elapsedTime());
#endif
d->doFullRepaint = d->firstLayout || root->printingMode();
if (d->repaintRects)
d->repaintRects->clear();
#if APPLE_CHANGES
// Now set our scrollbar state for the layout.
ScrollBarMode currentHMode = hScrollBarMode();
ScrollBarMode currentVMode = vScrollBarMode();
bool didFirstLayout = false;
if (d->firstLayout || (hMode != currentHMode || vMode != currentVMode)) {
suppressScrollBars(true);
if (d->firstLayout) {
d->firstLayout = false;
didFirstLayout = true;
// Set the initial vMode to AlwaysOn if we're auto.
if (vMode == Auto)
QScrollView::setVScrollBarMode(AlwaysOn); // This causes a vertical scrollbar to appear.
// Set the initial hMode to AlwaysOff if we're auto.
if (hMode == Auto)
QScrollView::setHScrollBarMode(AlwaysOff); // This causes a horizontal scrollbar to disappear.
}
if (hMode == vMode)
QScrollView::setScrollBarsMode(hMode);
else {
QScrollView::setHScrollBarMode(hMode);
QScrollView::setVScrollBarMode(vMode);
}
suppressScrollBars(false, true);
}
#else
QScrollView::setHScrollBarMode(hMode);
QScrollView::setVScrollBarMode(vMode);
#endif
int oldHeight = _height;
int oldWidth = _width;
_height = visibleHeight();
_width = visibleWidth();
if (oldHeight != _height || oldWidth != _width)
d->doFullRepaint = true;
RenderLayer* layer = root->layer();
if (!d->doFullRepaint) {
layer->computeRepaintRects();
root->repaintObjectsBeforeLayout();
}
root->layout();
m_part->invalidateSelection();
//kdDebug( 6000 ) << "TIME: layout() dt=" << qt.elapsed() << endl;
d->layoutSchedulingEnabled=true;
d->layoutSuppressed = false;
if (!root->printingMode())
resizeContents(layer->width(), layer->height());
// Now update the positions of all layers.
layer->updateLayerPositions(d->doFullRepaint);
#if APPLE_CHANGES
// We update our widget positions right after doing a layout.
root->updateWidgetPositions();
#endif
if (d->repaintRects && !d->repaintRects->isEmpty()) {
// FIXME: Could optimize this and have objects removed from this list
// if they ever do full repaints.
RenderObject::RepaintInfo* r;
QPtrListIterator<RenderObject::RepaintInfo> it(*d->repaintRects);
for ( ; (r = it.current()); ++it)
r->m_object->repaintRectangle(r->m_repaintRect);
d->repaintRects->clear();
}
d->layoutCount++;
#if APPLE_CHANGES
if (KWQAccObjectCache::accessibilityEnabled())
root->document()->getAccObjectCache()->postNotification(root, "AXLayoutComplete");
#endif
#if APPLE_CHANGES
updateDashboardRegions();
#endif
#if NOKIA_CHANGES
KWQ(m_part)->updateFocusableRectList();
KWQ(m_part)->bridge()->Client().LayoutChanged();
RenderPart* renderPart = KWQ(m_part)->bridge()->RenderPart();
if (renderPart && renderPart->element() && renderPart->element()->id() == ID_FRAME)
{
renderPart->setNeedsLayoutAndMinMaxRecalc();
}
#endif
if (root->needsLayout()) {
//qDebug("needs layout, delaying repaint");
scheduleRelayout();
return;
}
setStaticBackground(d->useSlowRepaints);
#if APPLE_CHANGES
if (didFirstLayout) {
m_part->didFirstLayout();
}
#endif
}
#if APPLE_CHANGES
void KHTMLView::updateDashboardRegions()
{
DOM::DocumentImpl* document = m_part->xmlDocImpl();
if (document->hasDashboardRegions()) {
QValueList<DashboardRegionValue> newRegions = document->renderer()->computeDashboardRegions();
QValueList<DashboardRegionValue> currentRegions = document->dashboardRegions();
document->setDashboardRegions(newRegions);
KWQ(m_part)->dashboardRegionsChanged();
}
}
#endif
//
// Event Handling
//
/////////////////
void KHTMLView::viewportMousePressEvent( QMouseEvent *_mouse )
{
if(!m_part->xmlDocImpl()) return;
SharedPtr<KHTMLView> protector(this);
int xm, ym;
viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
//kdDebug( 6000 ) << "\nmousePressEvent: x=" << xm << ", y=" << ym << endl;
d->isDoubleClick = false;
d->mousePressed = true;
DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MousePress );
m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
#if !APPLE_CHANGES
if (d->clickCount > 0 &&
QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance())
d->clickCount++;
else {
d->clickCount = 1;
d->clickX = xm;
d->clickY = ym;
}
#else
if (KWQ(m_part)->passSubframeEventToSubframe(mev)) {
invalidateClick();
return;
}
d->clickCount = _mouse->clickCount();
if (d->clickNode)
d->clickNode->deref();
d->clickNode = mev.innerNode.handle();
if (d->clickNode)
d->clickNode->ref();
#endif
bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),true,
d->clickCount,_mouse,true,DOM::NodeImpl::MousePress);
if (!swallowEvent) {
khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
QApplication::sendEvent( m_part, &event );
#if APPLE_CHANGES && !NOKIA_CHANGES
// Many AK widgets run their own event loops and consume events while the mouse is down.
// When they finish, currentEvent is the mouseUp that they exited on. We need to update
// the khtml state with this mouseUp, which khtml never saw.
// If this event isn't a mouseUp, we assume that the mouseUp will be coming later. There
// is a hole here if the widget consumes the mouseUp and subsequent events.
if (KWQ(m_part)->lastEventIsMouseUp()) {
d->mousePressed = false;
}
#endif
emit m_part->nodeActivated(mev.innerNode);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -