📄 kwqkhtmlpart.cpp
字号:
void KHTMLPart::frameDetached()
{
if (KWQ(this)->bridge())
KWQ(this)->bridge()->Client().FrameDetached();
// FIXME: There may be a better place to do this that works for KHTML too.
KHTMLPart *parent = parentPart();
if (parent) {
FrameList& parentFrames = parent->d->m_frames;
FrameIt end = parentFrames.end();
for (FrameIt it = parentFrames.begin(); it != end; ++it) {
ChildFrame &child = *it;
if (child.m_part == this) {
parent->disconnectChild(&child);
parentFrames.remove(it);
deref();
break;
}
}
}
}
void KWQKHTMLPart::urlSelected(const KURL &url, int button, int state, const URLArgs &args)
{
TEventCode code = EEventNull;
// ### NOT IMPLEMENTED proper event handling
_bridge->Client().LoadUrl(url.Des(),
_bridge->Referrer(), // referrer
args.reload, // reload
ETrue, //userGesture
args.frameName.Des(), //target
code //triggeringEvent
);
}
class KWQPluginPart : public ReadOnlyPart
{
virtual bool openURL(const KURL &) { return true; }
virtual bool closeURL() { return true; }
};
ReadOnlyPart *KWQKHTMLPart::createPart(const ChildFrame &child, const KURL &url, const QString &mimeType)
{
ReadOnlyPart *part = NULL;
TBool needFrame = _bridge->Client().FrameRequiredForMIMEType(mimeType.Des(), url.Des());
if (child.m_type == ChildFrame::Object && !needFrame)
{
CArrayFixFlat<TPtrC> *attributeNames = new CArrayFixFlat<TPtrC>(child.m_paramNames.count());
CArrayFixFlat<TPtrC> *attributeValues = new CArrayFixFlat<TPtrC>(child.m_paramValues.count());
if (!attributeNames || !attributeValues) {
delete attributeNames;
delete attributeValues;
return 0;
}
TRAPD(err,
for (uint i = 0; i < child.m_paramNames.count(); i++)
{ attributeNames->AppendL(child.m_paramNames[i].Des());}
for (uint i = 0; i < child.m_paramValues.count(); i++)
{ attributeValues->AppendL(child.m_paramValues[i].Des());}
);
KWQPluginPart *newPart = new KWQPluginPart;
if (err || !newPart) {
delete attributeNames;
delete attributeValues;
delete newPart;
return 0;
}
QObjectWidget* objectWidget = NULL;
objectWidget = new QObjectWidget(_bridge->Client().ViewForPluginWithURL(url.Des(),
*attributeNames,
*attributeValues,
d->m_doc->baseURL().Des(),
child.m_args.serviceType.Des()));
delete attributeNames;
delete attributeValues;
if (!objectWidget) {
delete newPart;
return 0;
}
newPart->setWidget(objectWidget);
part = newPart;
} else {
LOG(Frames, "name %s", child.m_name.ascii());
bool allowsScrolling = true;
int marginWidth = -1;
int marginHeight = -1;
if (child.m_type != ChildFrame::Object) {
HTMLFrameElementImpl *o = static_cast<HTMLFrameElementImpl *>(child.m_frame->element());
allowsScrolling = o->scrollingMode() != QScrollView::AlwaysOff;
marginWidth = o->getMarginWidth();
marginHeight = o->getMarginHeight();
}
CWebCoreBridge *childBridge = _bridge->Client().CreateChildFrameNamed (
child.m_name.Des(), //name
url.Des(), // url
child.m_args.metaData()["referrer"].Des(),
child.m_frame, // RenderPart
allowsScrolling, // allows scrolling
marginWidth, // margins
marginHeight );
// This call needs to return an object with a ref, since the caller will expect to own it.
// childBridge owns the only ref so far.
if (childBridge) {
childBridge->Part()->ref();
part = childBridge->Part();
}
}
return part;
}
void KWQKHTMLPart::setView(KHTMLView *view)
{
// Detach the document now, so any onUnload handlers get run - if
// we wait until the view is destroyed, then things won't be
// hooked up enough for some JavaScript calls to work.
if (d->m_doc && view == NULL) {
d->m_doc->detach();
}
if (view) {
view->ref();
}
if (d->m_view) {
d->m_view->deref();
}
d->m_view = view;
setWidget(view);
// Only one form submission is allowed per view of a part.
// Since this part may be getting reused as a result of being
// pulled from the back/forward cache, reset this flag.
_submittedFormURL = KURL();
}
KHTMLView *KWQKHTMLPart::view() const
{
return d->m_view;
}
void KWQKHTMLPart::setTitle(const DOMString &title)
{
QString text = title.string();
text.replace(QChar('\\'), backslashAsCurrencySymbol());
QString tlt;
// remove unexpected whitespace characters
for( int i=0; i<text.length(); ++i )
{
if( TChar( text[i] ).IsSpace() && text[i] != QChar(' ') ) continue;
tlt.append( text[i] );
}
_bridge->Client().SetTitle(tlt.Des());
}
void KWQKHTMLPart::setStatusBarText(const QString &status)
{
QString text = status;
text.replace(QChar('\\'), backslashAsCurrencySymbol());
_bridge->Client().SetStatusText(text.Des());
}
void KWQKHTMLPart::scheduleClose()
{
_bridge->Client().CloseWindowSoon();
}
void KWQKHTMLPart::unfocusWindow()
{
_bridge->Client().UnfocusWindow();
}
void KWQKHTMLPart::jumpToSelection()
{
// Assumes that selection start will only ever be text nodes. This is currently
// true, but will it always be so?
if (d->m_selection.start().isNotNull()) {
if (d->m_selection.start().node()->renderer()
&& d->m_selection.start().node()->renderer()->isText()) {
RenderText *rt = static_cast<RenderText *>(d->m_selection.start().node()->renderer());
//The selection may be in a child frame, but the scrolling is done by the
// main frame. So we have to recurse up the frame tree and get the
//global position of the selection rectangle and scroll the root frame
if (rt) {
QRect selectRect = rt->selectionRect();
KHTMLPart *rootPart = this;
int x = selectRect.x();
int y = selectRect.y();
while (rootPart->parentPart() != 0) {
x += rootPart->view()->x();
y += rootPart->view()->y();
rootPart = rootPart->parentPart();
}
selectRect.setX(x);
selectRect.setY(y);
selectRect.setHeight(selectRect.height() + d->m_view->visibleHeight()/2);
rootPart->view()->scrollTo(selectRect);
// query the element type of the selected text
TRect selRect;
TWebCoreFocusedElementType elType = EWebCoreElementNone;
TPoint pt;
pt.SetXY(rt->selectionRect().x() + 2, rt->selectionRect().y() + 2);
_bridge->NavigableNodeUnderCursor(pt, elType, selRect);
// now move the cursor to the selection area
pt.SetXY(selectRect.x() + 2, selectRect.y() + 2);
// convert pointer pos to view relative values
pt.SetXY(pt.iX - rootPart->view()->contentsX(), pt.iY - rootPart->view()->contentsY());
_bridge->Client().SetCursorPosition(pt, elType);
}
}
/*
Something like this would fix <rdar://problem/3154293>: "Find Next should not scroll page if the next target is already visible"
I think this would be a better way to do this, to avoid needless horizontal scrolling,
but it is not feasible until selectionRect() returns a tighter rect around the
selected text. Right now it works at element granularity.
NSView *docView = d->m_view->getDocumentView();
KWQ_BLOCK_EXCEPTIONS;
NSRect selRect = NSRect(selectionRect());
NSRect visRect = [docView visibleRect];
if (!NSContainsRect(visRect, selRect)) {
// pad a bit so we overscroll slightly
selRect = NSInsetRect(selRect, -10.0, -10.0);
selRect = NSIntersectionRect(selRect, [docView bounds]);
[docView scrollRectToVisible:selRect];
}
KWQ_UNBLOCK_EXCEPTIONS;
*/
}
}
void KWQKHTMLPart::redirectionTimerStartedOrStopped()
{
// ### NOT IMPLEMENTED redirects
/*
// Don't report history navigations, just actual redirection.
if (d->m_scheduledRedirection == historyNavigationScheduled) {
return;
}
KWQ_BLOCK_EXCEPTIONS;
if (d->m_redirectionTimer.isActive()) {
[_bridge reportClientRedirectToURL:KURL(d->m_redirectURL).getNSURL()
delay:d->m_delayRedirect
fireDate:[d->m_redirectionTimer.getNSTimer() fireDate]
lockHistory:d->m_redirectLockHistory
isJavaScriptFormAction:d->m_executingJavaScriptFormAction];
} else {
[_bridge reportClientRedirectCancelled:d->m_cancelWithLoadInProgress];
}
KWQ_UNBLOCK_EXCEPTIONS;
*/
}
void KWQKHTMLPart::paint(QPainter *p, const QRect &rect)
{
#ifndef NDEBUG
bool fillWithRed;
if (p->device()->devType() == QInternal::Printer)
fillWithRed = false; // Printing, don't fill with red (can't remember why).
else if (!xmlDocImpl() || xmlDocImpl()->ownerElement())
fillWithRed = false; // Subframe, don't fill with red.
else if (view() && view()->isTransparent())
fillWithRed = false; // Transparent, don't fill with red.
else if (_drawSelectionOnly)
fillWithRed = false; // Selections are transparent, don't fill with red.
else if (_elementToDraw != 0)
fillWithRed = false; // Element images are transparent, don't fill with red.
else
fillWithRed = true;
if (fillWithRed) {
p->fillRect(rect.x(), rect.y(), rect.width(), rect.height(), QColor(0xFF, 0, 0));
}
#endif
if (renderer()) {
// _elementToDraw is used to draw only one element
RenderObject *eltRenderer = (_elementToDraw != 0) ? _elementToDraw.handle()->renderer() : 0;
renderer()->layer()->paint(p, rect, _drawSelectionOnly, eltRenderer);
#ifdef __NAVIGATION_DEBUG__
// paint the dot as red circle
DocumentImpl *doc = xmlDocImpl();
if (doc) {
QPtrList<khtml::BoxInfo> *boxInfoList = new QPtrList<khtml::BoxInfo>;
QRect rt(0,0,view()->contentsWidth(),view()->contentsHeight());
doc->renderer()->getRenderersInRect(*boxInfoList,0,0,rt);
for(khtml::BoxInfo *sel = boxInfoList->first();sel;sel = boxInfoList->next()){
NodeImpl* n = sel->renderObject->node();
QRect nr = n->getRect();
if(n->isFocusable() || sel->area
|| n->getHTMLEventListener(EventImpl::MOUSEOVER_EVENT)
|| n->getHTMLEventListener(EventImpl::KHTML_CLICK_EVENT)
|| n->getHTMLEventListener(EventImpl::MOUSEUP_EVENT)) {
p->setPen(qRgb(255,0,0));
p->setBrush(NoBrush);
p->drawRect(sel->absoluteXPos,sel->absoluteYPos,sel->width,sel->height);
//p->drawEllipse(sel->absoluteXPos,sel->absoluteYPos,10,10);
}
}
boxInfoList->clear();
delete boxInfoList;
NodeImpl *node = doc->focusNode();
if (node)
{
QRect nr = node->getRect();
p->setPen(qRgb(255,0,0));
p->drawEllipse(d->m_view->getDot().x() + nr.left(), d->m_view->getDot().y() + nr.top(), 5,5);
}
}
#endif
} else {
ERROR("called KWQKHTMLPart::paint with nil renderer",0);
}
}
void KWQKHTMLPart::adjustPageHeight(int *newBottom, int oldTop, int oldBottom, int bottomLimit)
{
RenderCanvas *root = static_cast<RenderCanvas *>(xmlDocImpl()->renderer());
if (root) {
// Use a printer device, with painting disabled for the pagination phase
QPainter painter(true);
painter.setPaintingDisabled(true);
root->setTruncatedAt(oldBottom);
QRect dirtyRect(0,oldTop,
root->docWidth(), oldBottom-oldTop);
root->layer()->paint(&painter, dirtyRect);
*newBottom = root->bestTruncatedAt();
if (*newBottom == 0) {
*newBottom = oldBottom;
}
} else {
*newBottom = oldBottom;
}
}
RenderObject *KWQKHTMLPart::renderer() const
{
DocumentImpl *doc = xmlDocImpl();
return doc ? doc->renderer() : 0;
}
QString KWQKHTMLPart::userAgent() const
{
return QString::FromDes(_bridge->Client().UserAgentForURL(m_url.Des()));
//return QString("Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/179 (KHTML, like Gecko) Safari/179");
}
QString KWQKHTMLPart::mimeTypeForFileName(const QString &fileName) const
{
HBufC* _mimeType = _bridge->Client().MimeTypeForFileName(fileName.Des());
if(_mimeType) {
QString mimeType =QString::FromDes(*_mimeType);
delete _mimeType;
return mimeType ;
}
else{
return QString("");
}
}
#if !KHTML_NO_SCRIPTING
/*KJS::Bindings::RootObject *KWQKHTMLPart::bindingRootObject()
{
if (!_bindingRoot) {
_bindingRoot = new KJS::Bindings::RootObject(0); // The root gets deleted by JavaScriptCore.
KJS::ObjectImp *win = static_cast<KJS::ObjectImp *>(KJS::Window::retrieveWindow(this));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -