📄 khtmlview.cpp
字号:
#endif
}
bool KHTMLView::dispatchDragEvent(int eventId, DOM::NodeImpl *dragTarget, const QPoint &loc, DOM::ClipboardImpl *clipboard)
{
int clientX, clientY;
viewportToContents(loc.x(), loc.y(), clientX, clientY);
#if APPLE_CHANGES
QPoint screenLoc = viewportToGlobal(loc);
int screenX = screenLoc.x();
int screenY = screenLoc.y();
#else
#warning Need implementation of converting event location to screen location
int screenX = loc.x();
int screenY = loc.y();
#endif
bool ctrlKey = 0; // FIXME - set up modifiers, grab from AK or CG
bool altKey = 0;
bool shiftKey = 0;
bool metaKey = 0;
MouseEventImpl *me = new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
true, true, m_part->xmlDocImpl()->defaultView(),
0, screenX, screenY, clientX, clientY,
ctrlKey, altKey, shiftKey, metaKey,
0, 0, clipboard);
me->ref();
int exceptioncode = 0;
dragTarget->dispatchEvent(me, exceptioncode, true);
bool accept = me->defaultPrevented();
me->deref();
return accept;
}
bool KHTMLView::updateDragAndDrop(const QPoint &loc, DOM::ClipboardImpl *clipboard)
{
bool accept = false;
int xm, ym;
viewportToContents(loc.x(), loc.y(), xm, ym);
DOM::NodeImpl::MouseEvent mev(0, DOM::NodeImpl::MouseMove);
m_part->xmlDocImpl()->prepareMouseEvent(true, xm, ym, &mev);
DOM::Node newTarget = mev.innerNode;
// Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
if (newTarget.nodeType() == Node::TEXT_NODE) {
newTarget = newTarget.parentNode();
}
if (d->dragTarget != newTarget) {
// note this ordering is explicitly chosen to match WinIE
if (!newTarget.isNull()) {
accept = dispatchDragEvent(EventImpl::DRAGENTER_EVENT, newTarget.handle(), loc, clipboard);
}
if (!d->dragTarget.isNull()) {
dispatchDragEvent(EventImpl::DRAGLEAVE_EVENT, d->dragTarget.handle(), loc, clipboard);
}
} else if (!newTarget.isNull()) {
accept = dispatchDragEvent(EventImpl::DRAGOVER_EVENT, newTarget.handle(), loc, clipboard);
}
d->dragTarget = newTarget;
return accept;
}
void KHTMLView::cancelDragAndDrop(const QPoint &loc, DOM::ClipboardImpl *clipboard)
{
if (!d->dragTarget.isNull()) {
dispatchDragEvent(EventImpl::DRAGLEAVE_EVENT, d->dragTarget.handle(), loc, clipboard);
}
d->dragTarget = 0;
}
bool KHTMLView::performDragAndDrop(const QPoint &loc, DOM::ClipboardImpl *clipboard)
{
bool accept = false;
if (!d->dragTarget.isNull()) {
accept = dispatchDragEvent(EventImpl::DROP_EVENT, d->dragTarget.handle(), loc, clipboard);
}
d->dragTarget = 0;
return accept;
}
#if !APPLE_CHANGES
bool KHTMLView::focusNextPrevChild( bool next )
{
// Now try to find the next child
if (m_part->xmlDocImpl()) {
focusNextPrevNode(next);
if (m_part->xmlDocImpl()->focusNode() != 0)
return true; // focus node found
}
// If we get here, there is no next/previous child to go to, so pass up to the next/previous child in our parent
if (m_part->parentPart() && m_part->parentPart()->view()) {
return m_part->parentPart()->view()->focusNextPrevChild(next);
}
return QWidget::focusNextPrevChild(next);
}
void KHTMLView::doAutoScroll()
{
QPoint pos = QCursor::pos();
pos = viewport()->mapFromGlobal( pos );
int xm, ym;
viewportToContents(pos.x(), pos.y(), xm, ym);
pos = QPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y());
if ( (pos.y() < 0) || (pos.y() > visibleHeight()) ||
(pos.x() < 0) || (pos.x() > visibleWidth()) )
{
ensureVisible( xm, ym, 0, 5 );
}
}
#endif
#if NOKIA_CHANGES
bool KHTMLView::isLayoutPending() const
{
return d->layoutTimerId!=0;
}
#endif // NOKIA_CHANGES
DOM::NodeImpl *KHTMLView::nodeUnderMouse() const
{
return d->underMouse;
}
bool KHTMLView::scrollTo(const QRect &bounds)
{
d->scrollingSelf = true; // so scroll events get ignored
int x, y, xe, ye;
x = bounds.left();
y = bounds.top();
xe = bounds.right();
ye = bounds.bottom();
//kdDebug(6000)<<"scrolling coords: x="<<x<<" y="<<y<<" width="<<xe-x<<" height="<<ye-y<<endl;
int deltax;
int deltay;
int curHeight = visibleHeight();
int curWidth = visibleWidth();
if (ye-y>curHeight-d->borderY)
ye = y + curHeight - d->borderY;
if (xe-x>curWidth-d->borderX)
xe = x + curWidth - d->borderX;
// is xpos of target left of the view's border?
if (x < contentsX() + d->borderX )
deltax = x - contentsX() - d->borderX;
// is xpos of target right of the view's right border?
else if (xe + d->borderX > contentsX() + curWidth)
deltax = xe + d->borderX - ( contentsX() + curWidth );
else
deltax = 0;
// is ypos of target above upper border?
if (y < contentsY() + d->borderY)
deltay = y - contentsY() - d->borderY;
// is ypos of target below lower border?
else if (ye + d->borderY > contentsY() + curHeight)
deltay = ye + d->borderY - ( contentsY() + curHeight );
else
deltay = 0;
#if NOKIA_CHANGES
int maxx = INT_MAX;
int maxy = INT_MAX;
#else
int maxx = curWidth-d->borderX;
int maxy = curHeight-d->borderY;
#endif
int scrollX,scrollY;
scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax>-maxx ? deltax : -maxx);
scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay>-maxy ? deltay : -maxy);
if (contentsX() + scrollX < 0)
scrollX = -contentsX();
else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
scrollX = contentsWidth() - visibleWidth() - contentsX();
if (contentsY() + scrollY < 0)
scrollY = -contentsY();
// find in page hack:
// this enables bringing the end of document to the middle of view
//else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
//scrollY = contentsHeight() - visibleHeight() - contentsY();
scrollBy(scrollX, scrollY);
// generate abs(scroll.)
if (scrollX<0)
scrollX=-scrollX;
if (scrollY<0)
scrollY=-scrollY;
d->scrollingSelf = false;
if ( (scrollX!=maxx) && (scrollY!=maxy) )
return true;
else return false;
}
void KHTMLView::focusNextPrevNode(bool next)
{
// Sets the focus node of the document to be the node after (or if next is false, before) the current focus node.
// Only nodes that are selectable (i.e. for which isSelectable() returns true) are taken into account, and the order
// used is that specified in the HTML spec (see DocumentImpl::nextFocusNode() and DocumentImpl::previousFocusNode()
// for details).
DocumentImpl *doc = m_part->xmlDocImpl();
NodeImpl *oldFocusNode = doc->focusNode();
NodeImpl *newFocusNode;
// Find the next/previous node from the current one
if (next)
newFocusNode = doc->nextFocusNode(oldFocusNode);
else
newFocusNode = doc->previousFocusNode(oldFocusNode);
// If there was previously no focus node and the user has scrolled the document, then instead of picking the first
// focusable node in the document, use the first one that lies within the visible area (if possible).
if (!oldFocusNode && newFocusNode && d->scrollBarMoved) {
kdDebug(6000) << " searching for visible link" << endl;
bool visible = false;
NodeImpl *toFocus = newFocusNode;
while (!visible && toFocus) {
QRect focusNodeRect = toFocus->getRect();
if ((focusNodeRect.left() > contentsX()) && (focusNodeRect.right() < contentsX() + visibleWidth()) &&
(focusNodeRect.top() > contentsY()) && (focusNodeRect.bottom() < contentsY() + visibleHeight())) {
// toFocus is visible in the contents area
visible = true;
}
else {
// toFocus is _not_ visible in the contents area, pick the next node
if (next)
toFocus = doc->nextFocusNode(toFocus);
else
toFocus = doc->previousFocusNode(toFocus);
}
}
if (toFocus)
newFocusNode = toFocus;
}
d->scrollBarMoved = false;
if (!newFocusNode)
{
// No new focus node, scroll to bottom or top depending on next
if (next)
scrollTo(QRect(contentsX()+visibleWidth()/2,contentsHeight(),0,0));
else
scrollTo(QRect(contentsX()+visibleWidth()/2,0,0,0));
}
else {
// EDIT FIXME: if it's an editable element, activate the caret
// otherwise, hide it
if (newFocusNode->isContentEditable()) {
// make caret visible
}
else {
// hide caret
}
// Scroll the view as necessary to ensure that the new focus node is visible
if (oldFocusNode) {
if (!scrollTo(newFocusNode->getRect()))
return;
}
else {
ensureVisible(contentsX(), next ? 0: contentsHeight());
}
}
// Set focus node on the document
m_part->xmlDocImpl()->setFocusNode(newFocusNode);
emit m_part->nodeActivated(Node(newFocusNode));
#if 0
if (newFocusNode) {
// this does not belong here. it should run a query on the tree (Dirk)
// I'll fix this very particular part of the code soon when I cleaned
// up the positioning code
// If the newly focussed node is a link, notify the part
HTMLAnchorElementImpl *anchor = 0;
if ((newFocusNode->id() == ID_A || newFocusNode->id() == ID_AREA))
anchor = static_cast<HTMLAnchorElementImpl *>(newFocusNode);
if (anchor && !anchor->areaHref().isNull())
m_part->overURL(anchor->areaHref().string(), 0);
else
m_part->overURL(QString(), 0);
}
#endif
}
void KHTMLView::setMediaType( const QString &medium )
{
m_medium = medium;
}
QString KHTMLView::mediaType() const
{
#if APPLE_CHANGES
// See if we have an override type.
QString overrideType = KWQ(m_part)->overrideMediaType();
if (!overrideType.isNull())
return overrideType;
#endif
return m_medium;
}
#if !APPLE_CHANGES
void KHTMLView::print()
{
if(!m_part->xmlDocImpl()) return;
khtml::RenderCanvas *root = static_cast<khtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
if(!root) return;
// this only works on Unix - we assume 72dpi
KPrinter *printer = new KPrinter(QPrinter::PrinterResolution);
printer->addDialogPage(new KHTMLPrintSettings());
if(printer->setup(this)) {
viewport()->setCursor( waitCursor ); // only viewport(), no QApplication::, otherwise we get the busy cursor in kdeprint's dialogs
// set up KPrinter
printer->setFullPage(false);
printer->setCreator("KDE 3.0 HTML Library");
QString docname = m_part->xmlDocImpl()->URL();
if ( !docname.isEmpty() )
printer->setDocName(docname);
QPainter *p = new QPainter;
p->begin( printer );
khtml::setPrintPainter( p );
m_part->xmlDocImpl()->setPaintDevice( printer );
QString oldMediaType = mediaType();
setMediaType( "print" );
// We ignore margin settings for html and body when printing
// and use the default margins from the print-system
// (In Qt 3.0.x the default margins are hardcoded in Qt)
m_part->xmlDocImpl()->setPrintStyleSheet( printer->option("kde-khtml-printfriendly") == "true" ?
"* { background-image: none !important;"
" background-color: white !important;"
" color: black !important; }"
"body { margin: 0px !important; }"
"html { margin: 0px !important; }" :
"body { margin: 0px !important; }"
"html { margin: 0px !important; }"
);
QPaintDeviceMetrics metrics( printer );
// this is a simple approximation... we layout the document
// according to the width of the page, then just cut
// pages without caring about the content. We should do better
// in the future, but for the moment this is better than no
// printing support
kdDebug(6000) << "printing: physical page width = " << metrics.width()
<< " height = " << metrics.height() << endl;
root->setPrintingMode(true);
root->setWidth(metrics.width());
m_part->xmlDocImpl()->styleSelector()->computeFontSizes(&metrics);
m_part->xmlDocImpl()->updateStyleSelector();
root->setPrintImages( printer->option("kde-khtml-printimages") == "true");
root->setNeedsLayoutAndMinMaxRecalc();
root->layout();
// ok. now print the pages.
kdDebug(6000) << "printing: html page width = " << root->docWidth()
<< " height = " << root->docHeight() << endl;
kdDebug(6000) << "printing: margins left = " << printer->margins().width()
<< " top = " << printer->margins().height() << endl;
kdDebug(6000) << "printing: paper width = " << metrics.width()
<< " height = " << metrics.height() << endl;
// if the width is too large to fit on the paper we just scale
// the whole thing.
int pageHeight = metrics.height();
int pageWidth = metrics.width();
p->setClipRect(0,0, pageWidth, pageHeight);
if(root->docWidth() > metrics.width()) {
double scale = ((double) metrics.width())/((double) root->docWidth());
#ifndef QT_NO_TRANSFORMATIONS
p->scale(scale, scale);
#endif
pageHeight = (int) (pageHeight/scale);
pageWidth = (int) (pageWidth/scale);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -