/*
* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
#include <../bidi.h>
#include "config.h"
#include "WebCoreFrameBridge.h"
#include "frame.h"
#include "FrameLoader.h"
#include "FrameTree.h"
#include "FrameView.h"
#include "runtime_root.h"
#include "runtime.h"
#include "kjs_window.h"
#include "DOMWindow.h"
#include "document.h"
#include "documentloader.h"
#include "RenderPart.h"
#include "HTMLNames.h"
#include "EventNames.h"
#include "WebFrame.h"
#include "WebFrameView.h"
#include "WebView.h"
#include "WebUtil.h"
#include "brctl.h"
#include "settingsContainer.h"
#include "RenderView.h"
#include "Page.h"
#include "HTMLImageElement.h"
#include "RenderImage.h"
#include "StaticObjectsContainer.h"
#include "PlatformFontCache.h"
using namespace WebCore;
using namespace HTMLNames;
using namespace EventNames;
using KJS::Bindings::RootObject;
using KJS::ExecState;
using KJS::JSObject;
using KJS::Window;
const int KXHTMLDefaultFontMultiplier = 120;
const int KDefaultLowResFontMultiplier = 120;
const int KDefaultFontMultiplier = 140;
static PassRefPtr<RootObject> createRootObject(void* nativeHandle)
{
/* NSView *view = (NSView *)nativeHandle;
WebCoreFrameBridge *bridge = [[WebCoreViewFactory sharedFactory] bridgeForView:view];
if (!bridge)
return 0;
Frame* frame = bridge->_frame;
return frame->createRootObject(nativeHandle, frame->scriptProxy()->interpreter()); */
return NULL;
}
static void updateRenderingForBindings(ExecState* exec, JSObject* rootObject)
{
if (!rootObject)
return;
Window* window = static_cast<Window*>(rootObject);
if (!window)
return;
if (Document* doc = window->impl()->frame()->document())
doc->updateRendering();
}
static WebCoreFrameBridge* bridge(Frame* frame)
{
if (!frame)
return NULL;
return frame->bridge();
}
WebCoreFrameBridge::WebCoreFrameBridge() :
m_frame(0)
{
m_focusableNodeList.clear();
m_rtl = FALSE ;
}
WebCoreFrameBridge::~WebCoreFrameBridge()
{
}
void WebCoreFrameBridge::init()
{
static bool initializedKJS = false;
if (!initializedKJS) {
initializedKJS = true;
// s602 mac only?
//RootObject::setCreateRootObject(createRootObject);
KJS::Bindings::Instance::setDidExecuteFunction(updateRenderingForBindings);
}
m_shouldCreateRenderers = true;
}
void WebCoreFrameBridge::addJSExtension(const TDesC& id, KJS::JSObject* obj)
{
KJS::Window* window = KJS::Window::retrieveWindow(m_frame);
if (window) {
ExecState* exec = window->interpreter()->globalExec();
if (exec && obj) {
obj->setPrototype(window->interpreter()->builtinObjectPrototype());
window->put(exec, KJS::Identifier((const KJS::UChar *)id.Ptr(), id.Length()), obj, KJS::DontDelete);
}
}
}
WebCore::Frame* WebCoreFrameBridge::frame()
{
return m_frame;
}
void WebCoreFrameBridge::close()
{
clearFrame();
m_closed = true;
}
void WebCoreFrameBridge::addData(const char* data, int length)
{
Document *doc = m_frame->document();
// Document may be nil if the part is about to redirect
// as a result of JS executing during load, i.e. one frame
// changing another's location before the frame's document
// has been created.
if (doc) {
doc->setShouldCreateRenderers(shouldCreateRenderers());
m_frame->loader()->addData(data, length);
}
}
void WebCoreFrameBridge::receivedData(const char* data, int length, String textEncodingName)
{
// Set the encoding. This only needs to be done once, but it's harmless to do it again later.
String encoding;
if (m_frame)
encoding = m_frame->loader()->documentLoader()->overrideEncoding();
bool userChosen = !encoding.isNull() && !encoding.isEmpty();
if (encoding.isNull()||encoding.isEmpty())
encoding = textEncodingName;
if (m_frame && m_frame->loader())
m_frame->loader()->setEncoding(encoding, userChosen);
addData(data, length);
}
void WebCoreFrameBridge::clearFrame()
{
m_frame = NULL;
}
void WebCoreFrameBridge::createFrameViewWithScrollView(MWebCoreWidget* view, int marginWidth, int marginHeight)
{
// If we own the view, delete the old one - otherwise the render m_frame will take care of deleting the view.
if (m_frame)
m_frame->setView(NULL);
FrameView* frameView = new FrameView(m_frame);
m_frame->setView(frameView);
frameView->deref();
frameView->setView(view);
if (marginWidth >= 0)
frameView->setMarginWidth(marginWidth);
if (marginHeight >= 0)
frameView->setMarginHeight(marginHeight);
}
void WebCoreFrameBridge::forceLayoutAdjustingViewSize(bool flag)
{
m_frame->forceLayout(!flag);
if (flag)
m_frame->view()->adjustViewSize();
}
void WebCoreFrameBridge::forceLayoutWithMinimumPageWidth(float minPageWidth, float maxPageWidth, bool adjustingViewSize)
{
m_frame->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustingViewSize);
}
void WebCoreFrameBridge::sendResizeEvent()
{
m_frame->sendResizeEvent();
}
void WebCoreFrameBridge::sendScrollEvent()
{
m_frame->sendScrollEvent();
}
void WebCoreFrameBridge::installInFrame(MWebCoreWidget* view)
{
// If this isn't the main frame, it must have a render m_frame set, or it
// won't ever get installed in the view hierarchy.
ASSERT(m_frame == m_frame->page()->mainFrame() || m_frame->ownerElement());
m_frame->view()->setView(view);
// FIXME: frame tries to do this too, is it needed?
if (m_frame->ownerRenderer()) {
m_frame->ownerRenderer()->setWidget(m_frame->view());
// Now the render part owns the view, so we don't any more.
}
m_frame->view()->initScrollbars();
}
void WebCoreFrameBridge::setShouldCreateRenderers(bool f)
{
m_shouldCreateRenderers = f;
}
bool WebCoreFrameBridge::shouldCreateRenderers()
{
return m_shouldCreateRenderers;
}
bool WebCoreFrameBridge::needsLayout()
{
return m_frame->view() ? m_frame->view()->needsLayout() : false;
}
void WebCoreFrameBridge::setNeedsLayout()
{
if (m_frame->view())
m_frame->view()->setNeedsLayout();
}
TPtrC8 WebCoreFrameBridge::baseURL()
{
return m_frame->loader()->completeURL(m_frame->document()->baseURL()).des();
}
void WebCoreFrameBridge::updateFocusableRectList()
{
// layout is changed, focusrect list needs update
m_focusableNodeList.clear();
for(Node* n = frame()->document(); n != 0; n = n->traverseNextNode()) {
if(n->isFocusable() || n->hasTagName(areaTag))
m_focusableNodeList.append(n->getRect());
}
}
void WebCoreFrameBridge::updateThumbnail()
{
WebFrame* frame = kit(m_frame);
if (frame) {
frame->frameView()->topView()->updatePageScaler();
}
}
int WebCoreFrameBridge::textZoomPercent() const
{
// FIXME: need to hook up with screen size.
int sizeMultiplier = KXHTMLDefaultFontMultiplier;
if (m_frame->document() && m_frame->document()->htmlMode() != Document::XHtml) {
sizeMultiplier = StaticObjectsContainer::instance()->screenResolution() == ELowScreenResolution ?
KDefaultLowResFontMultiplier : KDefaultFontMultiplier;
}
#if PLATFORM(SYMBIAN)
TLanguage uilang = User::Language();
if(uilang == ELangKorean)
{
sizeMultiplier = 100;
}
#endif
if (control(m_frame)->settings())
sizeMultiplier = textMultiplier(control(m_frame)->settings()->brctlSetting(TBrCtlDefs::ESettingsFontSize), sizeMultiplier);
return sizeMultiplier;
}
bool WebCoreFrameBridge::searchFor(TPtrC string, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection)
{
return m_frame->findString(string, forward, caseFlag, wrapFlag, startInSelection);
}
void WebCoreFrameBridge::scalingFactorChanged(int factor)
{
StaticObjectsContainer::instance()->fontCache()->setFontZoomFactor(factor);
}
int WebCoreFrameBridge::maxBidiWidth()
{
if (m_frame) {
WebFrame* frame = kit(m_frame);
if (frame && frame->frameView())
return frame->frameView()->getBidiWidth();
}
return KMaxTInt;
}
void WebCoreFrameBridge::setWritingDirectionRtl(bool isRtl)
{
m_rtl = isRtl;
// update rtl only for mainframe
if (m_frame && m_frame == m_frame->page()->mainFrame()) {
if (control(m_frame)->brCtlLayoutObserver())
control(m_frame)->brCtlLayoutObserver()->NotifyLayoutChange(isRtl ? EOriginTopRight : EOriginTopLeft);
if (kit(m_frame->page())->pageScaler())
kit(m_frame->page())->pageScaler()->SetRelativePosition(0, 3, isRtl ? CPageScaler::ETopLeft : CPageScaler::ETopRight);
}
}
bool WebCoreFrameBridge::getTypeFromElement(Node* node, TBrCtlDefs::TBrCtlElementType& aElType, TRect& aFocusRect, Node*& aRNode) const
{
if(node && m_frame) {
// get the navigable node at this point
for (Node* n = node; n; n = n->parentNode()) {
if( n->isFocusable() ) {
aElType = nodeTypeB(n, m_frame);
aFocusRect = n->getRect();
aRNode = n;
return true;
}
else {
EventTargetNode* etn = NULL;
if (n->isEventTargetNode()) {
etn = EventTargetNodeCast(n);
}
if( etn && (etn->getHTMLEventListener(mouseoverEvent)
|| etn->getHTMLEventListener(mousedownEvent)
|| etn->getHTMLEventListener(mouseupEvent)) ) {
aFocusRect = n->getRect();
aElType = TBrCtlDefs::EElementMouseButtonListener;
aRNode = n;
return true;
}
else if (n->isElementNode() && n->hasTagName(areaTag)) {
HTMLElement* e = static_cast<HTMLElement*>(n);
if(!e->getAttribute(hrefAttr).isNull()) {
aElType = TBrCtlDefs::EElementAreaBox;
aFocusRect = n->getRect();
aRNode = n;
return true;
}
}
else if (n->isElementNode() && n->hasTagName(imgTag)) {
HTMLElement* e = static_cast<HTMLElement*>(n);
// First check if the image is inside an anchor
for (Node* np = n; np; np = np->parentNode()) {
if( np->hasTagName(aTag) ) {
HTMLElement* ep = static_cast<HTMLElement*>(np);
if(!ep->getAttribute(hrefAttr).isNull()) {
aElType = nodeTypeB(np, m_frame);
aFocusRect = np->getRect();
aRNode = np;
return true;
}
}
}
HTMLImageElement* imageElement = static_cast<HTMLImageElement *>(n);
RenderImage *r = static_cast<RenderImage *>(n->renderer());
CachedImage* ci = r->cachedImage();
if (ci && ci->errorOccurred()) {
aElType = TBrCtlDefs::EElementBrokenImage;
}
else {
String alttext = imageElement->altText();
if (alttext.find("nokia") != 0 && alttext.find("no_save") != 0) {
aElType = TBrCtlDefs::EElementImageBox;
}
else {
aElType = TBrCtlDefs::EElementNone;
}
}
aFocusRect = n->getRect().Rect();
aRNode = n;
return true;
}
else if (n->renderer() && n->renderer()->layer()) {
/*FIXME: to be implemneted for scrollbar
Scrollbar* hbar = n->renderer()->layer()->horizontalScrollbar();
if (hbar && IntRect(hbar->pos(),hbar->size()).contains(aPoint.iX,aPoint.iY)) {
aElType = EWebCoreElementScrollBar;
aFocusRect = IntRect(hbar->pos(),hbar->size()).Rect();
return true;
}
Scrollbar* vbar = n->renderer()->layer()->verticalScrollbar();
if (vbar && IntRect(vbar->pos(),vbar->size()).contains(aPoint.iX,aPoint.iY)) {
aElType = EWebCoreElementScrollBar;
aFocusRect = IntRect(vbar->pos(),vbar->size()).Rect();
return true;
}*/
}
}
}
}
return false;
}
// end of file