/*
* Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2006 David Smith (catfish.man@gmail.com)
* Copyright (C) 2007 Nokia
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <Browser_platform_variant.hrh>
#include "config.h"
#include "../../bidi.h"
#include "brctl.h"
#include "HistoryController.h"
#include "PageView.h"
#include "SettingsContainer.h"
#include "WebFrame.h"
#include "WebFrameBridge.h"
#include "WebFrameView.h"
#include "WebView.h"
#include "WebTabbedNavigation.h"
#include "WebChromeClient.h"
#include "WebCoreGraphicsContext.h"
#include "WebContextMenuClient.h"
#include "WebEditorClient.h"
#include "WebDragClient.h"
#include "WebFrameLoaderClient.h"
#include "WebInspectorClient.h"
#include "WebFepTextEditor.h"
#include "WebSurface.h"
#include "WebCursor.h"
#include "WebFormFill.h"
#include "WebFormFillPopup.h"
#include "WebToolBarInterface.h"
#include "WebPointerEventHandler.h"
#include "WebPageScrollHandler.h"
#include "WebPopupDrawer.h"
#include "PluginSkin.h"
#include "PluginWin.h"
#include "PluginPlayer.h"
#include "WebKitLogger.h"
#include "Page.h"
#include "Settings.h"
#include "Frame.h"
#include "FrameView.h"
#include "FrameTree.h"
#include "FrameLoader.h"
#include "HistoryItem.h"
#include "EventHandler.h"
#include "ResourceRequest.h"
#include "PlatformString.h"
#include "SelectionController.h"
#include "PlatformKeyboardEvent.h"
#include "PlatformScrollbar.h"
#include "DocumentLoader.h"
#include "StaticObjectsContainer.h"
#include "ToolBar.h"
#include "Document.h"
#include "FocusController.h"
#include "WebUtil.h"
#include "WidgetExtension.h"
#include "Cache.h"
#include "RenderWidget.h"
#include "HTMLNames.h"
#include "HTMLInputElement.h"
using namespace HTMLNames;
#include <AknUtils.h>
#include <CUserAgent.h>
#include "WebPageZoomHandler.h"
#include "PlatformFontCache.h"
#include "WebPageFullScreenHandler.h"
#include "eikon.hrh"
#include "WebScrollbarDrawer.h"
using namespace WebCore;
const int KRepaintDelayLoading = 500*1000; // dont do repaints more often than this during loading (0.5s)
const int KRepaintDelayComplete = 100*1000; // faster updates after load so dynamic scripts etc have better frame rate (0.1s)
const int KRepaintDelayNavNone = 70*1000;
const int KNormalScrollRange = 60;
const int KPanningStartSpeed = 30;
const int KPanningStartTime = 900;
const int KPanningPageScalerStart = 1300;
const int KPanningMaxSpeed = 90;
const int KPanningMaxTime = 3000;
const int KAllowSelection = 1;
const int KScalerVisibilityTime = 1100*1000; //1.1s
const int KCursorUpdateFrquency = 20*1000; // 20ms
const int KCursorInitialDelay = 200*1000; // 200ms
const TKeyEvent KNullKeyEvent = {0,0,0,0};
const int KSmallPageScale = 13*13; // if the area of page is less than 169% (130%*130%) of the viewport area, it's considered to be a small page
const int KZoomLevelDelta = 10; //set 10% for each increasment
const int KZoomLevelDefaultValue = 100;
const int KZoomLevelMaxValue = 200;
const int KZoomLevelMinValue = 10;
const int KZoomBgRectColor = 209;
const int KZoomDefaultLevel = 8; //100%
const int defaultCacheCapacity = 256 * 1024;
// LOCAL FUNCTION PROTOTYPES
TInt doRepaintCb( TAny* ptr );
TInt doFepCb( TAny* ptr );
static WebFrame* incrementFrame(WebFrame* curr, bool forward, bool wrapFlag)
{
Frame* coreFrame = core(curr);
return kit(forward
? coreFrame->tree()->traverseNextWithWrap(wrapFlag)
: coreFrame->tree()->traversePreviousWithWrap(wrapFlag));
}
// -----------------------------------------------------------------------------
// WebView::NewL
// Public Class Method
// Two-phased constructor.
// -----------------------------------------------------------------------------
WebView* WebView::NewL( CCoeControl& parent, CBrCtl* brctl )
{
WebView* self = new (ELeave) WebView( brctl );
CleanupStack::PushL( self );
self->ConstructL( parent );
CleanupStack::Pop(); // self
return self;
}
// -----------------------------------------------------------------------------
// WebView::CWebKitView
// Private Class Method
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
WebView::WebView( CBrCtl* brctl ) :
m_brctl(brctl)
, m_isEditable(false)
, m_currentEventKey(KNullKeyEvent)
, m_currentEventCode(EEventNull)
, m_scrollingSpeed(KNormalScrollRange*KZoomLevelDefaultValue/100)
, m_focusedElementType(TBrCtlDefs::EElementNone)
, m_pageScaler(NULL)
, m_pageScalerEnabled(false)
, m_inFindState(false)
, m_pageView(NULL)
, m_savedCursorPosition(KInitialOffset, KInitialOffset)
, m_findKeyword(NULL)
, m_webFormFill(NULL)
, m_fepTimer(0)
, m_isClosing(false)
, m_widgetextension(0)
, m_userAgent(NULL)
, m_pageZoomHandler(NULL)
, m_currentZoomLevel(KZoomLevelDefaultValue)
, m_lastZoomLevel(KZoomLevelMinValue)
, m_maxZoomLevel(KZoomLevelMaxValue)
, m_minZoomLevel(KZoomLevelMinValue)
, m_defaultZoomLevel(KZoomLevelDefaultValue)
, m_pageFullScreenHandler(NULL)
, m_viewIsScrolling(false)
, m_ptrbuffer(0)
, m_showCursor(false)
, m_allowRepaints(true)
{
}
WebView::~WebView()
{
// the zoom handler is a client of WebView (also owned by
// WebView--a circular dependency) so it must be deleted before
// the WebView object is destroyed because in its destructor it
// operates on the WebView object
delete m_pageZoomHandler;
m_pageZoomHandler = NULL;
m_zoomLevelArray.Close();
// prevent frameViews to access members when topView is
// closing down.
m_isClosing = true;
m_page->setGroupName(String());
if (m_fastScrollTimer)
m_fastScrollTimer->Cancel();
delete m_fastScrollTimer;
delete [] m_ptrbuffer;
delete m_repainttimer;
delete m_webfeptexteditor;
delete m_webcorecontext;
delete m_bitmapdevice;
delete m_page;
delete m_pageScaler;
delete m_pageView;
delete m_webFormFill;
delete m_toolbar;
delete m_toolbarinterface;
delete m_widgetextension;
delete m_webpointerEventHandler;
delete m_pageScrollHandler;
delete m_pluginplayer;
delete m_fepTimer;
delete m_popupDrawer;
delete m_tabbedNavigation;
delete m_userAgent;
delete m_pageFullScreenHandler;
delete m_bridge;
delete m_frameView;
}
// -----------------------------------------------------------------------------
// WebView::ConstructL
// Private Class Method
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
void WebView::ConstructL( CCoeControl& parent )
{
SetContainerWindowL(parent);
CCoeControl::MakeVisible(ETrue);
m_frameView = new WebFrameView();
m_page = new Page(new WebChromeClient(this), new WebContextMenuClient(), new WebEditorClient(this), new WebDragClient(), new WebInspectorClient());
m_page->backForwardList()->setCapacity(0);
m_page->setGroupName("com.s60.browser");
//
WebCore::Settings* settings = m_page->settings();
settings->setLoadsImagesAutomatically(true);
settings->setJavaScriptEnabled(true);
settings->setMinimumFontSize(7);
settings->setMinimumLogicalFontSize(9);
settings->setDefaultFontSize(12);
settings->setDefaultFixedFontSize(12);
settings->setPluginsEnabled(true);
settings->setJavaScriptCanOpenWindowsAutomatically(true);
settings->setPluginsEnabled(true);
m_tabbedNavigation = new WebTabbedNavigation(this);
m_bridge = new WebFrameBridge();
m_bridge->initMainFrameWithPage(m_page, "", m_frameView);
// Create and offscreen device and context
m_bitmapdevice = CFbsBitmapDevice::NewL( StaticObjectsContainer::instance()->webSurface()->offscreenBitmap() );
m_webcorecontext = WebCoreGraphicsContext::NewL( m_bitmapdevice, StaticObjectsContainer::instance()->webSurface()->offscreenBitmap(), mainFrame()->frameView());
//
m_repainttimer = CPeriodic::NewL(CActive::EPriorityHigh);
m_webfeptexteditor = new CWebFepTextEditor(this);
m_fastScrollTimer = CPeriodic::NewL(CActive::EPriorityHigh);
m_dirtyZoomMode = false;
m_currentZoomLevel = StaticObjectsContainer::instance()->fontCache()->fontZoomFactor();
m_startZoomLevel = m_currentZoomLevel;
m_pageZoomHandler = WebPageZoomHandler::NewL( *this );
if ( brCtl()->capabilities()&TBrCtlDefs::ECapabilityFitToScreen ) {
m_minZoomLevel = (KZoomLevelDefaultValue / m_pageZoomHandler->stepSize())*m_pageZoomHandler->stepSize();
//could happen only if m_minZoomLevel < stepSize
if (!m_minZoomLevel) m_minZoomLevel = m_pageZoomHandler->stepSize();
}
// construct the zoom array from the default level
m_zoomLevelArray.Append(KZoomLevelDefaultValue);
TInt toAddZoomLevel = KZoomLevelDefaultValue + KZoomLevelDefaultValue*KZoomLevelDelta/100;
while (toAddZoomLevel <= m_maxZoomLevel)
{
// add the zoom level after default one
m_zoomLevelArray.Append(toAddZoomLevel);
toAddZoomLevel = toAddZoomLevel + toAddZoomLevel*KZoomLevelDelta/100;
}
// now go the minimum one
toAddZoomLevel = KZoomLevelDefaultValue - KZoomLevelDefaultValue*KZoomLevelDelta/100;
while (toAddZoomLevel >= m_minZoomLevel)
{
//add the zoom level after default one
m_zoomLevelArray.Insert(toAddZoomLevel, 0);
toAddZoomLevel = toAddZoomLevel - toAddZoomLevel*KZoomLevelDelta/100;
}
m_pageFullScreenHandler = WebPageFullScreenHandler::NewL( *this );
if ( m_brctl->capabilities() & TBrCtlDefs::ECapabilityWebKitLite ) {
m_pageScalerEnabled = false;
}
else {
initializePageScalerL();
m_pageScalerEnabled = true;
}
if (m_brctl->capabilities() & TBrCtlDefs::ECapabilityAutoFormFill) {
m_webFormFill = new WebFormFill(this);
}
// Create the PointerEventHandler
m_ptrbuffer = new TPoint[256];
m_webpointerEventHandler = WebPointerEventHandler::NewL(this);
// Create the ScrollHandler
m_pageScrollHandler = WebPageScrollHandler::NewL( *this );
if (AknLayoutUtils::PenEnabled()) {
DrawableWindow()->SetPointerGrab(ETrue);
EnableDragEvents();
}
CUserAgent* usrAgnt = CUserAgent::NewL();
CleanupStack::PushL( usrAgnt );
HBufC8* userAgent8 = usrAgnt->UserAgentL();
CleanupStack::PushL( userAgent8 );
m_userAgent = HBufC::NewL(userAgent8->Length());
m_userAgent->Des().Copy(userAgent8->Des());
CleanupStack::PopAndDestroy(2); // userAgent8, usrAgnt
MakeViewVisible(ETrue);
m_isPluginsVisible=ETrue;
CCoeControl::SetFocus(ETrue);
cache()->setCapacities(0, 0, defaultCacheCapacity);
}
void WebView::initializePageScalerL()
{
TBool lowQuality = !( m_brctl->capabilities() & TBrCtlDefs::ECapabilityGraphicalHistory );
m_pageScaler = CPageScaler::NewL( *this, EColor64K, lowQuality );
m_pageScaler->SetVisible( EFalse );
//update the minimap support info from page scaler
m_pageScalerEnabled = (m_pageScaler->HasOverlaySupport());
}
void WebView::fepTimerFired(Timer<WebView>*)
{
CCoeEnv::Static()->SimulateKeyEventL(m_keyevent, m_eventcode);
}
//-------------------------------------------------------------------------------
// WebView::Draw ( from CCoeControl )
// BitBlts the offscreen bitmap to the GraphicsContext
//-------------------------------------------------------------------------------
void WebView::Draw( const TRect& rect ) const
{
if (StaticObjectsContainer::instance()->isPluginFullscreen()) return;
CWindowGc& gc = SystemGc();
CEikBorderedControl::Draw( rect );
// put offscreen bitmap onto the screen
if ( !m_dirtyZoomMode ) {
StaticObjectsContainer::instance()->webSurface()->flip( Rect().iTl, gc );
if (m_widgetextension){
m_widgetextension->DrawTransition(gc,StaticObjectsContainer::instance()->webSurface()->offscreenBitmap());
}
}
else {
gc.DrawBitmap( m_destRectForZooming, StaticObjectsContainer::instance()->webSurface()->offscreenBitmap(), m_srcRectForZooming );
if ( m_startZoomLevel > m_currentZoomLevel) {
TRect rectLeft( TPoint( rect.iTl.iX + m_destRectForZooming.Width() - 2, rect.iTl.iY ),
TPoint( rect.iBr ));
TRect rectBottom( TPoint( rect.iTl.iX, rect.iTl.iY + m_destRectForZooming.Height() - 2 ),
TPoint( rect.iBr.iX + m_destRectForZooming.Width(), rect.iBr.iY ));
const TRgb colorTest(KZoomBgRectColor,KZoomBgRectColor,KZoomBgRectColor);
gc.SetPenColor(colorTest);
gc.SetBrushStyle( CGraphicsContext::EForwardDiagonalHatchBrush );
gc.SetBrushColor(colorTest);
gc.DrawRect( rectLeft );
gc.DrawRect( rectBottom );
}
}
if (m_pageScalerEnabled && m_pageScaler->Visible()) {
m_pageScaler->Draw( gc, rect );
}
if (m_toolbar) {
m_toolbar->Draw();
}
if (m_popupDrawer)
{
m_popupDrawer->drawPopup();
}
if (m_widgetextension){
m_widgetextension->DrawTransition(gc,StaticObjectsContainer::instance()->webSurface()->offscreenBitmap());
}
}
WebCore::Page* WebView::page()
{
return m_page;
}
WebFrame* WebView::mainFrame()
{
if (!m_page)
return NULL;
return kit(m_page->mainFrame());
}
//-------------------------------------------------------------------------------
// WebView::syncRepaint
// Repaint the given rectangle synchronously
//-------------------------------------------------------------------------------
void WebView::syncRepaint( const TRect& rect)
{
m_repaints.AddRect( rect );
syncRepaint();
}
void WebView::MakeVisible(TBool visible)
{
if (visible == IsVisible()) return;
CCoeControl::MakeVisible(visible);
MakeViewVisible(visible);
}
void WebView::MakeViewVisible(TBool visible)
{
if ( visible ) {
// resize the offscreen surface, this is needed
// because the shared surface is changed.
StaticObjectsContainer::instance()->webSurface()->setView( this );
m_bitmapdevice->Resize( m_offscreenrect.Size() );
m_webcorecontext->resized();
}
WebCursor* cursor = StaticObjectsContainer::instance()->webCursor();
if (cursor) {
if (visible) {
cursor->setCurrentView(*this);
//Reset the iFocusedElementType to be the same as before the second window is opened.
cursor->setPosition(m_savedCursorPosition);
cursor->updatePositionAndElemType(m_savedCursorPosition);
} else
m_savedCursorPosition = cursor->position();
cursor->cursorUpdate(visible & !AknLayoutUtils::PenEnabled());
}
Frame* f = m_page->mainFrame();
while ( f ) {
PassRefPtr<HTMLCollection> objects = f->document()->objects();
for (Node* n = objects->firstItem(); n; n = objects->nextItem()) {
MWebCoreObjectWidget* w = widget(n);
if (w)
w->makeVisible(visible);
}
PassRefPtr<HTMLCollection> embeds = f->document()->embeds();
for (Node* n = embeds->firstItem(); n; n = embeds->nextItem()) {
MWebCoreObjectWidget* w = widget(n);
if (w)
w->makeVisible(visible);
}
f = f->tree()->traverseNext();
}
if ( m_pageScaler ) {
m_pageScaler->SetContainerRect(TRect(Rect().Size()));
}
if ( m_webFormFillPopup ){
// don't show the popup if view's visibility changes.
m_webFormFillPopup->MakeVisible(EFalse);
}
if ( visible ) {
clearOffScreenBitmap();
syncRepaint( mainFrame()->frameView()->visibleRect() );
}
}
void WebView::doLayout()
{
int zoomLevel = m_currentZoomLevel;
if(!( m_widgetextension && m_widgetextension->IsWidgetPublising())) {
zoomLevelChanged( KZoomLevelDefaultValue );
}
Frame* f = m_page->mainFrame();
while ( f ) {
f->sendResizeEvent();
f->view()->layout();
f = f->tree()->traverseNext();
}
// maybe it got bigger in layout?
TRect rect(m_repaints.BoundingRect());
TPoint p( mainFrame()->frameView()->contentPos());
rect.Move(-p);
// draw to back buffer
if(!( m_widgetextension && m_widgetextension->IsWidgetPublising())) {
mainFrame()->frameView()->draw( *m_webcorecontext, rect );
if ( zoomLevel < m_minZoomLevel ) zoomLevel = m_minZoomLevel;
zoomLevelChanged( zoomLevel );
}
}
//-------------------------------------------------------------------------------
// WebView::syncRepaint
// Repaint the current repaint region synchronously and clear it
//-------------------------------------------------------------------------------
void WebView::syncRepaint()
{
if (m_pageScaler && m_pageScaler->FullScreenMode()) {
ScaledPageChanged(m_pageScaler->Rect(), EFalse, EFalse);
return;
}
if (!IsVisible()) {
return;
}
if (StaticObjectsContainer::instance()->isPluginFullscreen()) return;
CFbsBitGc& gc = m_webcorecontext->gc();
gc.Reset();
TRect viewRect( mainFrame()->frameView()->visibleRect() );
TPoint p( mainFrame()->frameView()->contentPos());
Frame* f = m_page->mainFrame();
bool layoutPending = false;
while (f && !layoutPending) {
layoutPending = f->view()->layoutPending();
f = f->tree()->traverseNext();
}
if (layoutPending && m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeNone) {
Frame* f = m_page->mainFrame();
while ( f ) {
f->view()->layout();
f = f->tree()->traverseNext();
}
layoutPending = false;
}
if (!layoutPending) {
bool needsDraw = false;
m_repaints.Tidy();
for (int i=0; i<m_repaints.Count(); ++i) {
TRect r = m_repaints[i];
if (r.Intersects(viewRect)) {
r.Move(-p);
mainFrame()->frameView()->draw( *m_webcorecontext, r );
needsDraw = true;
}
}
if (needsDraw){
// blit the whole backbuffer to the screen (in Draw())
// This could be optimized further to blit only the affected area.
// Not a big win, scrolling is the most critical case and there you
// need to blit the whole buffer anyway.
m_brctl->DrawNow();
}
// dont do next async repaint until KRepaintDelay
m_repaints.Clear();
}
m_repainttimer->Cancel();
// tot:fixme TBool complete = iWebkitControl->IsProgressComplete(); && CImageRendererFactory::Instance()->DecodeCount()==0;
TBool complete = ETrue;
int timeout = complete ? KRepaintDelayComplete : KRepaintDelayLoading;
if (complete && m_brctl->settings() && m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeNone)
timeout = KRepaintDelayNavNone;
if ( !m_pageZoomHandler->isActive() && m_allowRepaints){
m_repainttimer->Start(timeout,
0, TCallBack( &doRepaintCb, this ) );
}
// need to draw formfill popup here.
if (m_webFormFillPopup && m_webFormFillPopup->IsVisible()) {
m_webFormFillPopup->reDraw();
}
}
//-------------------------------------------------------------------------------
// DoRepaintCb
// C-style TCallback function
//-------------------------------------------------------------------------------
TInt doRepaintCb(
TAny* ptr )
{
static_cast<WebView*>(ptr)->doRepaint();
return EFalse;
}
//-------------------------------------------------------------------------------
// WebView::doRepaint
// Perform a scheduled repaint
//-------------------------------------------------------------------------------
void WebView::doRepaint()
{
// the timer must always be canceled here!
m_repainttimer->Cancel();
// only repaint when this view owns the surface
if ( StaticObjectsContainer::instance()->webSurface()->topView() != this ) return;
// anything to do?
if ( !m_repaints.IsEmpty() ) {
syncRepaint( );
}
}
//-------------------------------------------------------------------------------
// WebView::collectOffscreenbitmap
// Get offscreen bitmap
//-------------------------------------------------------------------------------
void WebView::collectOffscreenbitmapL(CFbsBitmap& snapshot)
{
if ( snapshot.Handle() == 0) {
// Create bitmap only once
(snapshot).Create(m_brctl->Size(), StaticObjectsContainer::instance()->webSurface()->displayMode());
}
CFbsBitmapDevice* device = CFbsBitmapDevice::NewL( &snapshot);
CleanupStack::PushL(device);
WebCoreGraphicsContext* gc = WebCoreGraphicsContext::NewL( device, &snapshot, mainFrame()->frameView());
CleanupStack::PushL(gc);
if( snapshot.Handle() != 0 ){
// Clear previous offscreen bitmap
// frameView->draw might clear the bitmap.
gc->gc().Clear();
} else if (snapshot.SizeInPixels()!=m_brctl->Size()){
snapshot.Resize(m_brctl->Size());
}
mainFrame()->frameView()->draw( *gc, mainFrame()->frameView()->visibleRect() );
CleanupStack::PopAndDestroy(2);
}
//-------------------------------------------------------------------------------
// WebView::scheduleRepaint
// Schedule an asynchronous repaint
//-------------------------------------------------------------------------------
void WebView::scheduleRepaint(
const TRect& rect )
{
m_repaints.AddRect( rect );
if( m_widgetextension && m_widgetextension->IsWidgetPublising())
{
#ifdef BRDO_WRT_HS_FF
// Draw the miniview
m_brctl->brCtlLayoutObserver()->NotifyLayoutChange(EOriginTopLeft);
#endif
}
// if we are active, we'll repaint when timer fires
if( !m_repainttimer->IsActive() && !m_pageZoomHandler->isActive() &&
m_allowRepaints) {
// no timer yet, repaint immediatly (but asynchronously)
m_repainttimer->Start( 0, 0, TCallBack( &doRepaintCb, this ) );
}
}
void WebView::pageLoadFinished()
{
if (m_brctl->settings()) {
switch (m_brctl->settings()->getNavigationType()) {
case SettingsContainer::NavigationTypeTabbed:
m_tabbedNavigation->initializeForPage();
break;
case SettingsContainer::NavigationTypeNone:
break;
case SettingsContainer::NavigationTypeCursor:
{
// Temp solution to fix a problem with scrolling large pages:
// if user starts scrolling while loading a page - at the end of the load we should not restore
// the content position from the history controller
// As of now scroll events are not passed to WebCore and this will be changed in future
// then this code should be replaces with the commented one below
TPoint ptInit(0,0);
TPoint ptFromHistory = m_brctl->historyHandler()->historyController()->currentEntryPosition();
TPoint ptCurr = mainFrame()->frameView()->contentPos();
if ( ptCurr != ptFromHistory ) {
if ( ptInit == ptCurr ) {
mainFrame()->frameView()->scrollTo(ptFromHistory);
}
else {
m_brctl->historyHandler()->historyController()->updateCurrentEntryPositionIfNeeded();
}
}
/*
if ( !core(mainFrame())->view()->wasScrolledByUser())
mainFrame()->frameView()->scrollTo(m_brctl->historyHandler()->historyController()->currentEntryPosition());*/
break;
}
}
}
if (FrameLoadTypeStandard == core( mainFrame())->loader()->loadType()){
if (m_brctl->capabilities()&TBrCtlDefs::ECapabilityFitToScreen){
updateMinZoomLevel( mainFrame()->frameView()->contentSize());
}
}
setHistoryLoad(false);
setRedirectWithLockedHistory(false);
int zoomLevel = m_brctl->historyHandler()->historyController()->currentEntryZoomLevel();
if ( zoomLevel != m_currentZoomLevel) {
m_brctl->historyHandler()->historyController()->updateCurrentEntryZoomLevelIfNeeded();
}
if ( m_pageScaler ) {
m_pageScaler->DocumentCompleted();
TRAP_IGNORE(m_pageScaler->DocumentChangedL());
}
Node* focusedNode = NULL;
Frame* focusedFrame = page()->focusController()->focusedFrame();
if (focusedFrame)
{
focusedNode = focusedFrame->document()->focusedNode();
if (focusedNode) { // based on focused element
m_focusedElementType = nodeTypeB(focusedNode, focusedFrame);
}
else {
m_focusedElementType = TBrCtlDefs::EElementNone;
}
}
else {
m_focusedElementType = TBrCtlDefs::EElementNone;
}
m_brctl->updateDefaultSoftkeys();
}
void WebView::updatePageScaler()
{
if (m_brctl->capabilities() & TBrCtlDefs::ECapabilityGraphicalPage) {
TRAP_IGNORE(if (m_pageScaler) m_pageScaler->DocumentChangedL());
}
}
void WebView::openUrl(const TDesC& url)
{
mainFrame()->loadRequest(WebCore::ResourceRequest(url, true));
}
WebCore::DOMDocument* WebView::mainFrameDocument()
{
return mainFrame()->DOMDocument();
}
TBool WebView::shouldClose()
{
Frame* coreFrame = core(mainFrame());
if (!coreFrame)
return ETrue;
return coreFrame->shouldClose();
}
TBool WebView::isLoading()
{
return m_page->mainFrame()->loader()->activeDocumentLoader()->isLoading();
}
TInt WebView::CountComponentControls() const
{
int count = (m_webFormFillPopup && m_webFormFillPopup->IsVisible()) ? 1 : 0;
return count;
}
CCoeControl* WebView::ComponentControl(TInt aIndex) const
{
CCoeControl* rv = NULL;
if ( aIndex == 0)
if ( m_webFormFillPopup && m_webFormFillPopup->IsVisible()) rv = m_webFormFillPopup;
return rv;
}
bool WebView::isNaviKey(const TKeyEvent& keyevent)
{
return ( keyevent.iCode == EKeyUpArrow // North
|| keyevent.iCode == EKeyRightUpArrow // Northeast
|| keyevent.iCode == EStdKeyDevice11 // : Extra KeyEvent supports diagonal event simulator wedge
|| keyevent.iCode == EKeyRightArrow // East
|| keyevent.iCode == EKeyRightDownArrow // Southeast
|| keyevent.iCode == EStdKeyDevice12 // : Extra KeyEvent supports diagonal event simulator wedge
|| keyevent.iCode == EKeyDownArrow // South
|| keyevent.iCode == EKeyLeftDownArrow // Southwest
|| keyevent.iCode == EStdKeyDevice13 // : Extra KeyEvent supports diagonal event simulator wedge
|| keyevent.iCode == EKeyLeftArrow // West
|| keyevent.iCode == EKeyLeftUpArrow // Northwest
|| keyevent.iCode == EStdKeyDevice10);
}
bool WebView::handleEditable(const TKeyEvent& keyevent, TEventCode eventcode, Frame* frame )
{
bool consumed = false;
if (eventcode == EEventKeyDown)
return false;
consumed = frame->eventHandler()->keyEvent(PlatformKeyboardEvent(keyevent,eventcode));
// exit input on up/down key
// EXCEPT on touch-enabled devices. We'll just consume in that case
if ( !consumed && isNaviKey(keyevent) ) {
if (m_webfeptexteditor->validateTextFormat() ) {
setFocusNone();
}
else {
consumed = true;
}
}
return consumed;
}
bool WebView::handleEventKeyDown(const TKeyEvent& keyevent, TEventCode eventcode, Frame* frame)
{
m_currentEventKey = keyevent;
m_currentEventCode = eventcode;
return false; // not consumed
}
void WebView::sendMouseEventToEngine(TPointerEvent::TType eventType, TPoint pos, Frame* frame)
{
TPointerEvent event;
event.iPosition = pos;
event.iModifiers = 0;
event.iType = eventType;
switch (eventType) {
case TPointerEvent::EButton1Down:
{
frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(event));
break;
}
case TPointerEvent::EButton1Up:
{
frame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(event));
break;
}
case TPointerEvent::EMove:
{
frame->eventHandler()->handleMouseMoveEvent(PlatformMouseEvent(event));
break;
}
};
}
void WebView::setFocusedNode(Frame* frame)
{
Node* node = frame->eventHandler()->mousePressNode();
for (Node* n = node; n; n = n->parentNode()) {
if ( n->isFocusable() ) {
page()->focusController()->setFocusedNode(n, frame);
}
}
}
bool WebView::handleEventKeyL(const TKeyEvent& keyevent, TEventCode eventcode, Frame* frame)
{
WebCursor* cursor = StaticObjectsContainer::instance()->webCursor();
bool consumed = false;
TKeyEvent oldKeyEvent(m_currentEventKey);
oldKeyEvent.iCode = keyevent.iCode;
TEventCode oldKeyCode = m_currentEventCode;
bool downEventConsumed = false;
m_currentEventKey = keyevent;
m_currentEventCode = eventcode;
if (m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeNone) {
consumed = handleInputElement(keyevent, eventcode, frame);
if (!consumed)
consumed = sendKeyEventToEngine(keyevent, eventcode, frame);
}
else {
if (keyevent.iCode == EKeyDevice3) {
// pass it to webcore
sendMouseEventToEngine(TPointerEvent::EButton1Down,
cursor->position(), frame);
// mimic ccb's behavior of onFocus
setFocusedNode(frame);
// Toolbar is activated on long key press only if the element
// type is EElementNone during EEventKeyDown and EEventKey.
// This prevents toolbar from popping up in DHTML pages. Also,
// toolbar is activated when the user is not in fast scroll
// mode, or in page overview mode, or on wml page.
if ( ( m_focusedElementType == TBrCtlDefs::EElementNone ||
m_focusedElementType == TBrCtlDefs::EElementBrokenImage ) &&
keyevent.iRepeats && !m_brctl->wmlMode() ) {
launchToolBarL();
}
consumed = true;
}
else if (isNaviKey(keyevent)) {
if (oldKeyCode == EEventKeyDown){
// Keydown event is automatically generated before each keypress event, but in this case
// we don't send a keypress event, so send a keydown event explicitly.
downEventConsumed = sendKeyEventToEngine(oldKeyEvent, EEventKeyDown, frame);
}
if (m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeTabbed) {
consumed = downEventConsumed || handleTabbedNavigation(keyevent, eventcode);
}
else {
consumed = handleKeyNavigation(keyevent, eventcode, frame);
}
} // if (m_brctl->settings()->getNavigationType()
else { // Not an arrow key..
// activate hovered input element by just start typing
consumed = handleInputElement(keyevent, eventcode, frame);
}
if (!consumed && !(m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeTabbed && isNaviKey(keyevent))) {
consumed = sendKeyEventToEngine(keyevent, eventcode, frame);
}
}
return consumed;
}
bool WebView::handleInputElement(const TKeyEvent& keyevent, TEventCode eventcode, Frame* frame)
{
WebCursor* cursor = StaticObjectsContainer::instance()->webCursor();
bool sendMousedEvent = false;
if (m_focusedElementType == TBrCtlDefs::EElementInputBox ||
m_focusedElementType == TBrCtlDefs::EElementTextAreaBox) {
sendMousedEvent = true;
}
else if (m_focusedElementType == TBrCtlDefs::EElementSelectBox ||
m_focusedElementType == TBrCtlDefs::EElementSelectMultiBox) {
if (m_brctl->settings()->getNavigationType() != SettingsContainer::NavigationTypeNone || keyevent.iCode == EKeyDevice3) {
sendMousedEvent = true;
}
}
if (sendMousedEvent) {
sendMouseEventToEngine(TPointerEvent::EButton1Down, cursor->position(), frame);
sendMouseEventToEngine(TPointerEvent::EButton1Up, cursor->position(), frame);
if (m_focusedElementType == TBrCtlDefs::EElementInputBox ||
m_focusedElementType == TBrCtlDefs::EElementTextAreaBox) {
if (!m_fepTimer) {
m_fepTimer = new WebCore::Timer<WebView>(this, &WebView::fepTimerFired);
}
m_fepTimer->startOneShot(0.2f);
setEditable(true);
}
m_keyevent = keyevent;
m_eventcode = eventcode;
return true;
}
return false; // not input element
}
bool WebView::handleKeyNavigation(const TKeyEvent& keyevent, TEventCode eventcode, Frame* frame)
{
WebCursor* cursor = StaticObjectsContainer::instance()->webCursor();
bool consumed = false;
bool fastscroll(m_fastScrollTimer->IsActive());
// start fast scrolling
m_showCursor = true;
if (!cursor->isVisible()) {
cursor->cursorUpdate(true);
}
m_savedPosition = mainFrame()->frameView()->contentPos();
cursor->scrollAndMoveCursor(keyevent.iCode, m_scrollingSpeed, fastscroll);
updateScrollbars();
if (!fastscroll) {
m_fastScrollTimer->Start(KCursorInitialDelay,KCursorUpdateFrquency,TCallBack(&scrollTimerCb,this));
m_scrollingStartTime.HomeTime();
}
// and minimap comes on
consumed = handleMinimapNavigation();
if (!fastscroll) {
sendMouseEventToEngine(TPointerEvent::EMove, cursor->position(), frame);
}
consumed = true;
return consumed;
}
bool WebView::handleMinimapNavigation()
{
int scrollingTime = millisecondsScrolled();
if (!AknLayoutUtils::PenEnabled() && m_pageScalerEnabled &&
m_pageScaler && !isSmallPage() &&
m_brctl->settings()->brctlSetting(TBrCtlDefs::ESettingsPageOverview) &&
(scrollingTime > KPanningPageScalerStart || m_pageScaler->Visible())) {
m_pageScaler->SetVisibleUntil(KScalerVisibilityTime);
}
return true;
}
bool WebView::handleTabbedNavigation(const TKeyEvent& keyevent, TEventCode eventcode)
{
int horizontal = 0;
int vertical = 0;
switch(keyevent.iCode) {
case EKeyUpArrow: // North
vertical = -1;
break;
case EKeyRightUpArrow: // Northeast
case EStdKeyDevice11: // : Extra KeyEvent supports diagonal event simulator wedge
vertical = -1;
horizontal = +1;
break;
case EKeyRightArrow: // East
horizontal = +1;
break;
case EKeyRightDownArrow: // Southeast
case EStdKeyDevice12: // : Extra KeyEvent supports diagonal event simulator wedge
vertical = +1;
horizontal = +1;
break;
case EKeyDownArrow: // South
vertical = +1;
break;
case EKeyLeftDownArrow: // Southwest
case EStdKeyDevice13: // : Extra KeyEvent supports diagonal event simulator wedge
vertical = +1;
horizontal = -1;
break;
case EKeyLeftArrow: // West
horizontal = -1;
break;
case EKeyLeftUpArrow: // Northwest
case EStdKeyDevice10: // : Extra KeyEvent supports diagonal event simulator wedge
vertical = -1;
horizontal = -1;
break;
default: // (Should never get here)
break;
}
return m_tabbedNavigation->navigate(horizontal, vertical);
}
bool WebView::handleEventKeyUp(const TKeyEvent& keyevent, TEventCode eventcode, Frame* frame)
{
bool consumed = false;
TInt delay = 2 * KCursorInitialDelay;
WebCursor* cursor = StaticObjectsContainer::instance()->webCursor();
m_fastScrollTimer->Cancel();
m_scrollingSpeed = KNormalScrollRange*100/scalingFactor();
if (viewIsFastScrolling()) {
setViewIsFastScrolling(false);
sendMouseEventToEngine(TPointerEvent::EMove, cursor->position(), frame);
toggleRepaintTimer(true);
if (!inPageViewMode()) {
delay = 0;
}
}
m_pageScrollHandler->scrollbarDrawer()->fadeScrollbar(delay);
if ( (keyevent.iScanCode == EStdKeyDevice3) ||
(keyevent.iScanCode == EStdKeyEnter) ) {
// pass it to webcore
if (m_focusedElementType == TBrCtlDefs::EElementInputBox ||
m_focusedElementType == TBrCtlDefs::EElementTextAreaBox) {
setEditable(true);
}
if (m_brctl->settings()->getNavigationType() != SettingsContainer::NavigationTypeNone) {
sendMouseEventToEngine(TPointerEvent::EButton1Up, cursor->position(), frame);
consumed = true;
}
}
if (!consumed) {
TKeyEvent correctedKeyEvent(keyevent);
correctedKeyEvent.iCode = m_currentEventKey.iCode;
sendKeyEventToEngine(correctedKeyEvent, eventcode, frame);
}
m_currentEventKey = KNullKeyEvent;
m_currentEventCode = EEventNull;
return consumed;
}
bool WebView::sendKeyEventToEngine(const TKeyEvent& keyevent,
TEventCode eventcode, Frame* frame)
{
bool consumed = frame->eventHandler()->keyEvent(PlatformKeyboardEvent(keyevent,eventcode));
if (!consumed && eventcode == EEventKey &&
(m_brctl->capabilities() & TBrCtlDefs::ECapabilityAccessKeys)) {
TKeyEvent ke = keyevent;
TChar c(ke.iCode);
// Not consumed by WebCore, is alphanumeric and does not have any modifier
if (c.IsAlphaDigit() &&
!(ke.iModifiers & (EModifierCtrl | EModifierAlt | EModifierShift))) {
ke.iModifiers = EModifierCtrl;
frame->eventHandler()->keyEvent(PlatformKeyboardEvent(ke,EEventKeyDown));
consumed = true;
}
}
return consumed;
}
TKeyResponse WebView::OfferKeyEventL(const TKeyEvent& keyevent, TEventCode eventcode )
{
WebCursor* cursor = StaticObjectsContainer::instance()->webCursor();
//hijack
if (isSynchRequestPending()) {
return EKeyWasNotConsumed;
}
if (m_toolbar)
return m_toolbar->HandleOfferKeyEventL(keyevent, eventcode);
if (m_popupDrawer)
return m_popupDrawer->handleOfferKeyEventL(keyevent, eventcode );
if ( m_webFormFillPopup && m_webFormFillPopup->IsVisible() && AknLayoutUtils::PenEnabled() ) {
if (EKeyWasConsumed == m_webFormFillPopup->HandleKeyEventL(keyevent, eventcode)) {
return EKeyWasConsumed;
}
}
bool consumed = false;
Frame* coreFrame = core(mainFrame());
if (!coreFrame)
return EKeyWasNotConsumed;
coreFrame = page()->focusController()->focusedOrMainFrame();
// edit events
if (m_isEditable) {
consumed = handleEditable(keyevent, eventcode, coreFrame);
}
// scroll events
if (!consumed) {
switch( eventcode ) {
case EEventKeyDown:
handleEventKeyDown(keyevent, eventcode, coreFrame);
break;
case EEventKey:
if (keyevent.iScanCode != m_currentEventKey.iScanCode ) return EKeyWasNotConsumed;
consumed = handleEventKeyL(keyevent, eventcode, coreFrame);
break;
case EEventKeyUp:
consumed = handleEventKeyUp(keyevent, eventcode, coreFrame);
break;
}
}
return (consumed) ? EKeyWasConsumed : EKeyWasNotConsumed;
}
void WebView::updateScrollbars(int documentHeight, int displayPosY, int documentWidth, int displayPosX)
{
m_brctl->updateScrollbars((documentHeight * scalingFactor()) / 100, Rect().Height(),
(displayPosY * scalingFactor()) / 100, (documentWidth * scalingFactor()) / 100, Rect().Width(),
(displayPosX * scalingFactor()) / 100);
}
void WebView::updateScrollbars()
{
TPoint scrollDelta = mainFrame()->frameView()->contentPos() - m_savedPosition;
scrollDelta.iX *= 100;
scrollDelta.iY *= 100;
if (!inPageViewMode()) {
if (scrollDelta.iX == 0 && scrollDelta.iY == 0) {
m_pageScrollHandler->scrollbarDrawer()->drawScrollbar(this);
}
else {
m_pageScrollHandler->scrollbarDrawer()->drawScrollbar(this, scrollDelta);
}
}
}
void WebView::openPageViewL()
{
// don't show pageview if we are in lite mode
if ( m_brctl->capabilities() & TBrCtlDefs::ECapabilityWebKitLite )
return;
if (!m_pageView) {
m_pageView = CPageView::NewL(*this);
MakeVisible(EFalse);
m_savedPosition = mainFrame()->frameView()->contentPos();
m_brctl->reportStateChanged(TBrCtlDefs::EStateThumbnailView, ETrue);
}
}
void WebView::closePageView()
{
if ( m_brctl->capabilities() & TBrCtlDefs::ECapabilityWebKitLite )
return;
if (m_pageView) {
delete m_pageView;
m_pageView = 0;
MakeVisible(ETrue);
m_brctl->DrawNow();
m_brctl->reportStateChanged(TBrCtlDefs::EStateThumbnailView, EFalse);
}
}
void WebView::cancelPageView()
{
if ( m_brctl->capabilities() & TBrCtlDefs::ECapabilityWebKitLite )
return;
if (m_pageView) {
mainFrame()->frameView()->scrollTo(m_savedPosition);
closePageView();
}
}
//-------------------------------------------------------------------------------
// WebView::launchToolBarL
//-------------------------------------------------------------------------------
void WebView::launchToolBarL()
{
if ( AknLayoutUtils::PenEnabled() || m_brctl->wmlMode() ) {
return;
}
if ( !(m_brctl->capabilities() & TBrCtlDefs::ECapabilityToolBar) ) {
return;
}
if ( !m_brctl->settings()->brctlSetting(TBrCtlDefs::ESettingsToolbarOnOff) ) {
return;
}
delete m_toolbar;
m_toolbar = 0;
delete m_toolbarinterface;
m_toolbarinterface = 0;
m_toolbarinterface = new WebToolBarInterface(this);
TRAPD(leave, m_toolbar = CToolBar::NewL(*m_toolbarinterface));
if (leave != KErrNone)
return;
/*EnableDragEvents();*/
m_brctl->DrawNow();
m_brctl->reportStateChanged(TBrCtlDefs::EStateToolBarMode, ETrue);
}
//-------------------------------------------------------------------------------
// WebView::closeToolBarL
//-------------------------------------------------------------------------------
void WebView::closeToolBarL()
{
delete m_toolbar;
m_toolbar = 0;
delete m_toolbarinterface;
m_toolbarinterface = 0;
if (IsVisible())
{
StaticObjectsContainer::instance()->webCursor()->cursorUpdate(ETrue);
m_brctl->DrawNow();
}
m_brctl->reportStateChanged(TBrCtlDefs::EStateToolBarMode, EFalse);
}
//-------------------------------------------------------------------------------
// WebView::DrawDocumentPart ( from MPageScalerCallback )
//
//
//-------------------------------------------------------------------------------
void WebView::DrawDocumentPart(
CFbsBitGc& aGc,
CFbsBitmap* aBitmap,
const TRect& aDocumentAreaToDraw )
{
TRect r( mainFrame()->frameView()->toDocCoords(aDocumentAreaToDraw) ) ;
WebCoreGraphicsContext* wcgc = 0;
TRAPD( err, wcgc = WebCoreGraphicsContext::NewL( aGc, aBitmap, mainFrame()->frameView()));
if ( err == KErrNone )
{
// ensure all documents have valid layout
// tot:fixme
//mainFrame->LayoutRecursive();
TWebCoreSavedContext saved( wcgc->save() );
wcgc->setOrigin( -aDocumentAreaToDraw.iTl );
wcgc->setClippingRect( aDocumentAreaToDraw );
// draw using bridge directly as frame::draw clips drawing to view size
mainFrame()->paintRect( *wcgc, r );
wcgc->restore(saved);
delete wcgc;
}
}
//-------------------------------------------------------------------------------
// WebView::DocumentViewport ( from MPageScalerCallback )
//
//
//-------------------------------------------------------------------------------
TRect WebView::DocumentViewport()
{
return mainFrame()->frameView()->toViewCoords(mainFrame()->frameView()->visibleRect());
}
//-------------------------------------------------------------------------------
// WebView::ScaledPageChanged ( from MPageScalerCallback )
//
//
//-------------------------------------------------------------------------------
void WebView::ScaledPageChanged(
const TRect& aRect,
TBool aFullScreen,
TBool aScroll )
{
if (!aScroll) {
Window().Invalidate( aRect );
}
if ( !aScroll && aFullScreen )
{
// update the history with new bitmap
CFbsBitmap* scaledPage = m_pageScaler->ScaledPage();
if (scaledPage) {
// Get the browser control rect
TRAP_IGNORE( m_brctl->historyHandler()->historyController()->updateHistoryEntryThumbnailL(scaledPage));
m_brctl->HandleBrowserLoadEventL( TBrCtlDefs::EEventThumbnailAvailable, 0, 0 );
}
// ignore err since we will use the default image
}
}
//-------------------------------------------------------------------------------
// WebView::DocumentSize ( from MPageScalerCallback )
//
//
//-------------------------------------------------------------------------------
TSize WebView::DocumentSize()
{
return mainFrame()->frameView()->toViewCoords(mainFrame()->frameView()->contentSize());
}
//-------------------------------------------------------------------------------
// WebView::TouchScrolling ( from MPageScalerCallback )
//
//
//-------------------------------------------------------------------------------
TBool WebView::TouchScrolling()
{
return m_pageScrollHandler->touchScrolling();
}
CCoeControl& WebView::PageControlView()
{
return *(m_brctl->CCoeControlParent());
}
void WebView::setEditable(TBool editable)
{
Frame* frame = core(mainFrame());
if (!frame || m_isEditable == editable)
return;
m_isEditable = editable;
Node* focusedNode = NULL;
Frame* focusedFrame = page()->focusController()->focusedFrame();
if (editable && focusedFrame) {
m_webfeptexteditor->UpdateEditingMode();
focusedNode = focusedFrame->document()->focusedNode();
}
else {
m_webfeptexteditor->CancelEditingMode();
}
WebCursor* c = StaticObjectsContainer::instance()->webCursor();
//
if (focusedNode)
// based on focused element
m_focusedElementType = nodeTypeB(focusedNode, focusedFrame);
else {
m_focusedElementType = TBrCtlDefs::EElementNone;
// based on cursor pos
c->updatePositionAndElemType(c->position());
}
c->cursorUpdate(!m_isEditable);
m_brctl->updateDefaultSoftkeys();
iCoeEnv->InputCapabilitiesChanged();
}
TCoeInputCapabilities WebView::InputCapabilities() const
{
return m_webfeptexteditor->InputCapabilities();
}
void WebView::FocusChanged(TDrawNow aDrawNow)
{
if (m_pageFullScreenHandler && m_pageFullScreenHandler->isFullScreenMode()) {
if (IsFocused()) m_pageFullScreenHandler->showEscBtnL();
else m_pageFullScreenHandler->hideEscBtnL();
}
}
void WebView::SizeChanged()
{
adjustOffscreenRect();
//
if (mainFrame()) {
mainFrame()->frameView()->setRect(mainFrame()->frameView()->toDocCoords(Rect()));
}
if ( m_pageScaler )
m_pageScaler->SetContainerRect(TRect(Rect().Size()));
if (m_webFormFillPopup && m_webFormFillPopup->IsVisible()) {
m_webFormFill->updatePopupView();
}
if (m_pageFullScreenHandler) {
m_pageFullScreenHandler->SizeChanged();
}
if (m_pageScrollHandler) {
m_pageScrollHandler->scrollbarDrawer()->redrawScrollbar();
}
}
TSize WebView::maxBidiSize() const
{
return TSize((Rect().Size().iWidth-20),(Rect().Size().iHeight-20));
}
void WebView::clearOffScreenBitmap()
{
m_webcorecontext->gc().Reset();
m_webcorecontext->gc().Clear();
}
void WebView::scrollBuffer(TPoint to, TPoint from, TBool usecopyscroll)
{
TRect rect(m_offscreenrect);
TSize bufSize( rect.Size() );
CFbsBitGc& gc = m_webcorecontext->gc();
gc.Reset();
TRect paintArea;
int dx = from.iX - to.iX;
int dy = from.iY - to.iY;
if (usecopyscroll && abs(dx) < bufSize.iWidth && abs(dy) < bufSize.iHeight) {
TPoint fromPt(dx<0?-dx:0, dy<0?-dy:0);
TRect fromRt(fromPt, TSize(bufSize.iWidth-abs(dx), bufSize.iHeight-abs(dy)));
TRect toRt(TPoint(fromPt.iX+dx, fromPt.iY+dy), fromRt.Size());
gc.CopyRect(TPoint(dx, dy), fromRt);
RRegion region;
region.AddRect(TRect(TPoint(0, 0), bufSize));
region.AddRect(toRt);
region.SubRect(toRt, 0);
for (int i=0; i<region.Count(); ++i) {
TRect r = region[i];
r.Move(to);
r = mainFrame()->frameView()->toDocCoords(r);
if (mainFrame()->frameView()->isScaled())
r.Grow(1, 1);
m_repaints.AddRect(r);
}
}
else {
TRect r(to, bufSize);
r = mainFrame()->frameView()->toDocCoords(r);
if (mainFrame()->frameView()->isScaled())
r.Grow(1, 1);
m_repaints.AddRect(r);
}
}
int WebView::scalingFactor() const
{
return m_currentZoomLevel;
}
CPluginHandler* WebView::pluginForExtension(const WebCore::String& pluginExtension)
{
return NULL;
}
bool WebView::isMIMETypeRegisteredAsPlugin(const WebCore::String& MIMEType)
{
return false;
}
void WebView::adjustOffscreenRect()
{
TRect rect(Rect());
if ( m_offscreenrect != rect ) {
m_offscreenrect = rect;
TSize bmSize = StaticObjectsContainer::instance()->webSurface()->offscreenBitmap()->SizeInPixels();
if (bmSize.iWidth != rect.Width() || bmSize.iHeight != rect.Height()) {
m_bitmapdevice->Resize(rect.Size());
m_webcorecontext->resized();
}
}
}
void WebView::autoScroll()
{
// update scrolling speed
int milli = millisecondsScrolled();
setViewIsFastScrolling(true);
toggleRepaintTimer(false);
m_scrollingSpeed = milli>=KPanningMaxTime ? KPanningMaxSpeed : KPanningStartSpeed+(KPanningMaxSpeed-KPanningStartSpeed)*Max(milli-KPanningStartTime,0)/KPanningMaxTime;
m_scrollingSpeed = m_scrollingSpeed*100/scalingFactor();
OfferKeyEventL(m_currentEventKey, EEventKey);
}
int WebView::millisecondsScrolled() const
{
TTime timeNow;
timeNow.HomeTime();
return I64INT(timeNow.MicroSecondsFrom(m_scrollingStartTime).Int64()/1000);
}
TInt WebView::scrollTimerCb(TAny* aAny)
{
WebView* v = static_cast<WebView*>(aAny);
v->autoScroll();
return ETrue;
}
int WebView::searchFor(const TPtrC& keyword)
{
m_inFindState = true;
delete m_findKeyword;
m_findKeyword = NULL;
m_findKeyword = keyword.Alloc();
if (!m_findKeyword || keyword.Length() == 0) {
WebFrame* frame = mainFrame()->findFrameWithSelection();
if(frame)
frame->clearSelection();
return TBrCtlDefs::EFindNoMatches;
}
m_findKeyword->Des().LowerCase();
return search(keyword, true, true);
}
int WebView::searchAgain(bool forward)
{
if (!m_findKeyword) {
WebFrame* frame = mainFrame()->findFrameWithSelection();
if(frame) {
frame->clearSelection();
}
return TBrCtlDefs::EFindNoMatches;
}
return search(*m_findKeyword, forward, true);
}
int WebView::search(TPtrC keyword, bool forward, bool wrapFlag)
{
// Get the frame holding the selection, or start with the main frame
WebFrame* startFrame = mainFrame()->findFrameWithSelection();
WebFrame* lastFrame = NULL;
if (!startFrame) {
if (StaticObjectsContainer::instance()->webCursor()) {
startFrame = StaticObjectsContainer::instance()->webCursor()->getFrameUnderCursor();
}
else {
startFrame = mainFrame();
}
}
WebFrame* frame = startFrame;
do {
WebFrame* nextFrame = incrementFrame(frame, forward, wrapFlag);
bool onlyOneFrame = (frame == nextFrame);
if (frame == startFrame)
lastFrame = frame;
bool foundString = false;
// In some cases we have to search some content twice; see comment later in this method.
// We can avoid ever doing this in the common one-frame case by passing YES for wrapFlag
// here, and then bailing out before we get to the code that would search again in the
// same content.
bool wrapOnThisPass = wrapFlag && onlyOneFrame;
if (!core(frame)->isFrameSet() ) {
foundString = frame->bridge()->searchFor(keyword, forward, false, wrapOnThisPass, true);
}
if (foundString) {
if (frame != startFrame)
startFrame->clearSelection();
return TBrCtlDefs::EFindMatch;
}
if (onlyOneFrame) {
startFrame->clearSelection();
return TBrCtlDefs::EFindNoMatches;
}
frame = nextFrame;
} while (frame && frame != startFrame);
// If there are multiple frames and wrapFlag is true and we've visited each one without finding a result, we still need to search in the
// first-searched frame up to the selection. However, the API doesn't provide a way to search only up to a particular point. The only
// way to make sure the entire frame is searched is to pass YES for the wrapFlag. When there are no matches, this will search again
// some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice.
// To fix this, we'd need to add a mechanism to specify a range in which to search.
if (wrapFlag && lastFrame) {
if (frame->bridge()->searchFor(keyword, forward, false, true, false))
return TBrCtlDefs::EFindMatch;
}
if (frame) {
frame->clearSelection();
}
return TBrCtlDefs::EFindNoMatches;
}
void WebView::exitFindState()
{
m_inFindState = false;
delete m_findKeyword;
m_findKeyword = NULL;
WebFrame* selectedFrame = mainFrame()->findFrameWithSelection();
selectedFrame->clearSelection();
}
bool WebView::isSmallPage()
{
TSize docSize = DocumentSize();
TSize viewSize = DocumentViewport().Size();
return ((docSize.iWidth * docSize.iHeight*100)/(viewSize.iWidth*viewSize.iHeight) < KSmallPageScale);
}
void WebView::willSubmitForm(FormState* formState)
{
if (m_webFormFill) {
m_webFormFill->willSubmitForm(formState);
}
}
//-------------------------------------------------------------------------------
// WebView::HandlePointerBufferReadyL
// Handles pointer move events
//-------------------------------------------------------------------------------
void WebView::HandlePointerBufferReadyL()
{
memset(m_ptrbuffer,0,256*sizeof(TPoint));
TPtr8 ptr((TUint8 *)m_ptrbuffer,256*sizeof(TPoint));
TInt numPnts = Window().RetrievePointerMoveBuffer(ptr);
int i = 0;
if (m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeNone) {
if (numPnts > 20)
i = numPnts - 20;
}
for (; i < numPnts; i++) {
TPointerEvent pe;
pe.iType = TPointerEvent::EDrag;
pe.iPosition = m_ptrbuffer[i];
m_webpointerEventHandler->HandlePointerEventL(pe);
}
}
//-------------------------------------------------------------------------------
// WebView::HandlePointerEventL
// Handles pointer events
//-------------------------------------------------------------------------------
void WebView::HandlePointerEventL(const TPointerEvent& aPointerEvent)
{
m_webpointerEventHandler->HandlePointerEventL(aPointerEvent);
}
void WebView::notifyMetaData(String& name, String& value)
{
if (name == "navigation") {
if (value == "tabbed") {
m_brctl->settings()->setNavigationType(SettingsContainer::NavigationTypeTabbed);
StaticObjectsContainer::instance()->webCursor()->cursorUpdate(true);
}
else if (value == "none") {
m_brctl->settings()->setNavigationType(SettingsContainer::NavigationTypeNone);
}
}
}
//-------------------------------------------------------------------------------
// WebView::handleShowAnchorHrefL
// Display a popup with the url of an anchor
//-------------------------------------------------------------------------------
void WebView::handleShowAnchorHrefL()
{
HBufC* url = NULL;
IntPoint p;
WebFrame* f = frameAndPointUnderCursor(p, *this);
String urlStr = getNodeUrlAtPointInFrame(*f, p);
if (urlStr.length() > 0)
url = urlStr.des().AllocL();
else
User::Leave(KErrNotSupported);
CleanupStack::PushL(url);
TRect elRect;
TBrCtlDefs::TBrCtlElementType elType = TBrCtlDefs::EElementNone;
WebFrame* frm = StaticObjectsContainer::instance()->webCursor()->getFrameUnderCursor();
WebCursor* cursor = StaticObjectsContainer::instance()->webCursor();
TPoint pt(frm->frameView()->viewCoordsInFrameCoords(cursor->position()));
StaticObjectsContainer::instance()->webCursor()->navigableNodeUnderCursor(*(frm), pt, elType, elRect);
TRect rect(elRect);
rect.SetRect(f->frameView()->frameCoordsInViewCoords(rect.iTl), f->frameView()->frameCoordsInViewCoords(rect.iBr));
TPtrC urlPtr(url->Des());
m_popupDrawer = WebPopupDrawer::NewL(*this, urlPtr, rect);
DrawNow();
CleanupStack::PopAndDestroy(); // url
}
//-------------------------------------------------------------------------------
// WebView::focusedImageLC
// Return the image that is under the cursor
//-------------------------------------------------------------------------------
TBrCtlImageCarrier* WebView::focusedImageLC()
{
if (m_focusedElementType != TBrCtlDefs::EElementImageBox && m_focusedElementType != TBrCtlDefs::EElementAreaBox) {
User::Leave(KErrNotSupported);
}
TBrCtlImageCarrier* imageCarrier = NULL;
User::LeaveIfError(focusedImage(this, imageCarrier));
CleanupStack::PushL(imageCarrier);
return imageCarrier;
}
//-------------------------------------------------------------------------------
// WebView::loadFocusedImageL
// Load the image that is under the cursor
//-------------------------------------------------------------------------------
void WebView::loadFocusedImageL()
{
// Ensure cursor is on a broken image and image loading is disabled
if (m_focusedElementType != TBrCtlDefs::EElementBrokenImage || m_brctl->settings()->brctlSetting(TBrCtlDefs::ESettingsAutoLoadImages)) {
User::Leave(KErrNotSupported);
}
loadFocusedImage(this);
}
//-------------------------------------------------------------------------------
// WebView::removePopup
// Delete the popupDrawer
//-------------------------------------------------------------------------------
void WebView::removePopup()
{
if (m_popupDrawer) {
delete m_popupDrawer;
m_popupDrawer = NULL;
DrawNow();
}
}
//-------------------------------------------------------------------------------
// WebView::zoomLevels
//-------------------------------------------------------------------------------
RArray<TUint>* WebView::zoomLevels()
{
return &m_zoomLevelArray;
}
//-------------------------------------------------------------------------------
// WebView::setZoomLevel
//-------------------------------------------------------------------------------
void WebView::setZoomLevel(int zoomLevel)
{
m_dirtyZoomMode = false;
if (zoomLevel < KZoomLevelMinValue ||
zoomLevel > m_maxZoomLevel ||
zoomLevel == m_currentZoomLevel)
return;
zoomLevelChanged(zoomLevel);
}
//-------------------------------------------------------------------------------
// WebView::setBitmapZoomLevel
//-------------------------------------------------------------------------------
void WebView::setBitmapZoomLevel(int zoomLevel)
{
m_zoomLevelChangedByUser = true;
WebFrameView* view = mainFrame()->frameView();
if (!view) return;
m_dirtyZoomMode = true;
m_isPluginsVisible = false;
mainFrame()->makeVisiblePlugins(false);
if (zoomLevel > m_startZoomLevel) {
// cut m_srcRectForZooming from m_offscreenrect and enlarge it to fit the view rect
float newWidth = m_offscreenrect.Width() * zoomLevel / m_startZoomLevel;
float newHeight = m_offscreenrect.Height() * zoomLevel / m_startZoomLevel;
newWidth = (float)(m_offscreenrect.Width() * (float)m_offscreenrect.Width()) / newWidth;
newHeight = (float)m_offscreenrect.Height() * (float)m_offscreenrect.Height() / newHeight;
TSize docSize = DocumentSize();
TSize viewSize = DocumentViewport().Size();
TSize contentSize = view->contentSize();
m_srcRectForZooming.iTl.iX = 0;
m_srcRectForZooming.iTl.iY = 0;
m_srcRectForZooming.iBr.iX = newWidth;
m_srcRectForZooming.iBr.iY = newHeight;
m_destRectForZooming = Rect();
}
else {
// take the whole rect and calculate new rect to fit it the rest of view rect paint gray colour
TInt newWidth = m_offscreenrect.Width() * zoomLevel / m_startZoomLevel;
TInt newHeight = m_offscreenrect.Height() * zoomLevel / m_startZoomLevel;
m_srcRectForZooming = m_offscreenrect;
m_destRectForZooming.iTl.iX = 0;
m_destRectForZooming.iTl.iY = 0;
m_destRectForZooming.iBr.iX = newWidth;
m_destRectForZooming.iBr.iY = newHeight;
}
m_currentZoomLevel = zoomLevel;
DrawNow();
}
//-------------------------------------------------------------------------------
// WebView::restoreZoomLevel
//-------------------------------------------------------------------------------
void WebView::restoreZoomLevel(int zoomLevel)
{
m_dirtyZoomMode = false;
clearOffScreenBitmap();
zoomLevelChanged(zoomLevel);
mainFrame()->notifyPluginsOfScrolling();
m_isPluginsVisible = false;
mainFrame()->makeVisiblePlugins(true);
m_isPluginsVisible = true;
}
//-------------------------------------------------------------------------------
// WebView::resetZoomLevel
//-------------------------------------------------------------------------------
void WebView::resetZoomLevel(void)
{
if( m_widgetextension ) {
return ;
}
if (m_historyLoad) {
int zoomLevel = m_brctl->historyHandler()->historyController()->currentEntryZoomLevel();
if (!zoomLevel) zoomLevel = KZoomLevelDefaultValue;
if (m_currentZoomLevel != zoomLevel) {
m_currentZoomLevel = zoomLevel;
}
int minZoomLevel = m_brctl->historyHandler()->historyController()->currentEntryMinZoomLevel();
if (!minZoomLevel)
minZoomLevel = (KZoomLevelDefaultValue/ m_pageZoomHandler->stepSize())*m_pageZoomHandler->stepSize();
else
minZoomLevel = (minZoomLevel / m_pageZoomHandler->stepSize())*m_pageZoomHandler->stepSize();
//could happen only if m_minZoomLevel < stepSize
if (!m_minZoomLevel) m_minZoomLevel = m_pageZoomHandler->stepSize();
if (m_minZoomLevel != minZoomLevel) {
m_minZoomLevel = minZoomLevel;
}
m_currentZoomLevel = zoomLevel;
//set to settings
m_brctl->settings()->setBrctlSetting(TBrCtlDefs::ESettingsCurrentZoomLevelIndex, m_currentZoomLevel);
}
else {
if (m_currentZoomLevel != KZoomLevelDefaultValue)
//set default current zoom index
{
m_currentZoomLevel = KZoomLevelDefaultValue;
//set to settings
m_brctl->settings()->setBrctlSetting(TBrCtlDefs::ESettingsCurrentZoomLevelIndex, m_currentZoomLevel);
}
}
clearOffScreenBitmap();
m_zoomLevelChangedByUser = false;
mainFrame()->scalingFactorChanged(m_currentZoomLevel);
mainFrame()->frameView()->setRect(mainFrame()->frameView()->toDocCoords(Rect()));
m_startZoomLevel = m_currentZoomLevel;
}
//-------------------------------------------------------------------------------
// WebView::updateMinZoomLevel
//-------------------------------------------------------------------------------
void WebView::updateMinZoomLevel(TSize size)
{
int newMinZoomLevel;
if (size.iWidth && size.iHeight) {
TRect screenSize(Rect().Size());
float minWidth = ((float)screenSize.Width()) * 100 /(float)( size.iWidth);
float minHeight = ((float)screenSize.Height()) * 100 /(float)( size.iHeight);
newMinZoomLevel = ( minWidth > minHeight )?minWidth:minHeight;
if ( newMinZoomLevel < KZoomLevelMinValue ) newMinZoomLevel = KZoomLevelMinValue;
if ( newMinZoomLevel > KZoomLevelDefaultValue ) newMinZoomLevel = KZoomLevelDefaultValue;
if ( newMinZoomLevel > m_currentZoomLevel ) newMinZoomLevel = m_currentZoomLevel;
}
else {
newMinZoomLevel = KZoomLevelDefaultValue;
}
newMinZoomLevel = (newMinZoomLevel/m_pageZoomHandler->stepSize())*m_pageZoomHandler->stepSize();
TBool needsUpdateArray = EFalse;
//Update the new array
if ( m_minZoomLevel!= newMinZoomLevel)
{
needsUpdateArray = ETrue;
}
//could happen only if m_minZoomLevel < stepSize
if (!newMinZoomLevel) newMinZoomLevel = m_pageZoomHandler->stepSize();
if (m_minZoomLevel != newMinZoomLevel)
{
m_minZoomLevel = newMinZoomLevel;
if (m_pageZoomHandler->isActive()) {
TRAP_IGNORE(
m_pageZoomHandler->hideZoomSliderL();
m_pageZoomHandler->showZoomSliderL();
);
}
else {
UpdateZoomArray(); //for non-touch
}
} //endof if (m_minZoomLevel != newMinZoomLevel)
}
//-------------------------------------------------------------------------------
// WebView::UpdateZoomArray
//-------------------------------------------------------------------------------
void WebView::UpdateZoomArray()
{
//only for non-touch device
if (m_pageZoomHandler->isActive())
{
return;
}
m_zoomLevelArray.Reset();
m_minZoomLevel = TInt(m_minZoomLevel/10) * 10;
m_zoomLevelArray.Append(KZoomLevelDefaultValue);
//construct the zoom array from the default level
TInt toAddZoomLevel = KZoomLevelDefaultValue + KZoomLevelDefaultValue*KZoomLevelDelta/100;
while (toAddZoomLevel <= m_maxZoomLevel)
{
//add the zoom level after default one
m_zoomLevelArray.Append(toAddZoomLevel);
toAddZoomLevel = toAddZoomLevel + toAddZoomLevel*KZoomLevelDelta/100;
}
//now goes the minimum one
toAddZoomLevel = KZoomLevelDefaultValue - KZoomLevelDefaultValue*KZoomLevelDelta/100;
while (toAddZoomLevel >= m_minZoomLevel)
{
//add the zoom level after default one
m_zoomLevelArray.Insert(toAddZoomLevel, 0);
toAddZoomLevel = toAddZoomLevel - toAddZoomLevel*KZoomLevelDelta/100;
}
}
//-------------------------------------------------------------------------------
// WebView::zoomLevelChanged
//-------------------------------------------------------------------------------
void WebView::zoomLevelChanged(int newZoomLevel)
{
int currZoomLevel = m_startZoomLevel;
m_dirtyZoomMode = false;
// instead of clearOffScreen bitmap, just reset.
m_webcorecontext->gc().Reset();
m_currentZoomLevel = newZoomLevel;
TSize sz( m_offscreenrect.Size() );
WebFrameView* view = mainFrame()->frameView();
if (!view) return;
TPoint pt( view->contentPos() );
TSize contentSize( view->contentSize() );
int z = m_currentZoomLevel;
if ( pt.iX * z > contentSize.iWidth * z - sz.iWidth * 100 )
pt.iX = ( contentSize.iWidth - sz.iWidth * 100 / z );
if ( pt.iY * z > contentSize.iHeight * z - sz.iHeight * 100 )
pt.iY = ( contentSize.iHeight - sz.iHeight * 100 / z );
if ( pt.iY < 0 ) pt.iY = 0;
if ( pt.iX < 0 ) pt.iX = 0;
view->setContentPos( pt );
mainFrame()->scalingFactorChanged(z);
view->checkScrollbarVisibility();
TRect rect = view->rect();
TInt tlx = (rect.iTl.iX * currZoomLevel) / m_currentZoomLevel;
TInt tly = (rect.iTl.iY * currZoomLevel) / m_currentZoomLevel;
TInt brx = (rect.iBr.iX * currZoomLevel) / m_currentZoomLevel;
TInt bry = (rect.iBr.iY * currZoomLevel) / m_currentZoomLevel;
// rounding
if (( rect.iTl.iX * currZoomLevel) % m_currentZoomLevel ){
tlx -= 1;
}
if (( rect.iTl.iY * currZoomLevel) % m_currentZoomLevel ){
tly -= 1;
}
if ((rect.iBr.iX * currZoomLevel) % m_currentZoomLevel ){
brx += 1;
}
if ((rect.iBr.iY * currZoomLevel) % m_currentZoomLevel ){
bry += 1;
}
view->setRect(TRect(tlx, tly, brx, bry));
// now just do a repaint, should be very fast
if ( currZoomLevel > newZoomLevel ) {
clearOffScreenBitmap();
}
m_startZoomLevel = m_currentZoomLevel;
updateScrollbars(mainFrame()->frameView()->contentSize().iHeight, mainFrame()->frameView()->contentPos().iY,
mainFrame()->frameView()->contentSize().iWidth, mainFrame()->frameView()->contentPos().iX);
syncRepaint(view->visibleRect());
int zoomLevel = m_brctl->historyHandler()->historyController()->currentEntryZoomLevel();
if (zoomLevel != m_currentZoomLevel) m_brctl->historyHandler()->historyController()->updateCurrentEntryZoomLevelIfNeeded();
}
//-------------------------------------------------------------------------------
// WebView:::resetLastZoomLevelIfNeeded
//-------------------------------------------------------------------------------
void WebView::resetLastZoomLevelIfNeeded()
{
if (m_lastZoomLevel == m_maxZoomLevel)
m_lastZoomLevel = 100;
}
//-----------------------------------------------------------------------------
// WebView::setZoomLevelAdaptively()
//-----------------------------------------------------------------------------
void WebView::setZoomLevelAdaptively()
{
int zoomLevel = KZoomLevelDefaultValue;
// Double Tap Zooming: it toggles between default, maxiZoomLevel.
// Depending on the current zoom level:
// A. If the current is already the max, it zooms to the max
// B. If the current is bigger than/equal to the default zoom level zooms to the default, it zooms to the max
// C. Otherwise it zooms to the default level first.
// For the mobile pages, such as google.com and cnn.com, minimum zoom level equals
// to the default zoom level. Zooming is only possible between default and maximum
// zoom level, double tap only won't reach logic C
//
// For both mobile and non-mobile pages, it creates the same end user double tap
// experiences
if (m_currentZoomLevel == m_maxZoomLevel ) {
zoomLevel = KZoomLevelDefaultValue;
}
else if (m_currentZoomLevel >= KZoomLevelDefaultValue ) {
zoomLevel = m_maxZoomLevel;
}
else {
zoomLevel = KZoomLevelDefaultValue;
}
// move the content
WebFrameView* view = mainFrame()->frameView();
if (!view) return;
WebCursor* cursor = StaticObjectsContainer::instance()->webCursor();
if (cursor) {
TPoint pt = cursor->position();
int z = zoomLevel * 100 / m_currentZoomLevel;
int xOff = (pt.iX * z / 100 - pt.iX)*100/zoomLevel;
int yOff = (pt.iY * z / 100 - pt.iY)*100/zoomLevel;
TPoint cp = view->contentPos();
cp += TPoint(xOff, yOff);
view->setContentPos(cp);
}
// zoom it
m_lastZoomLevel = m_currentZoomLevel;
setZoomLevel(zoomLevel);
mainFrame()->notifyPluginsOfScrolling();
}
//-------------------------------------------------------------------------------
// WebView::openPluginPlayerL
// Called when user clicks a plugin which is able to accept user input,
// this feature is only used in US build
//-------------------------------------------------------------------------------
void WebView::openPluginPlayerL(PluginWin* plugin)
{
if (!m_pluginplayer) {
PluginSkin* pluginskin = mainFrame()->focusedPlugin();
if ( !pluginskin || !pluginskin->isInteractive() ) return;
// we only create the player when the plugin content is ready and
// the plugin is not allowed to interact inside html page.
if ( pluginskin->CanInteract() ) return;
m_pluginplayer = PluginPlayer::NewL( *m_brctl, plugin );
MakeVisible(EFalse);
m_brctl->reportStateChanged(TBrCtlDefs::EStatePluginPlayer, ETrue);
// now start playing the content
m_pluginplayer->start();
}
}
void WebView::setFocusNone()
{
page()->focusController()->setFocusedNode(NULL, page()->focusController()->focusedOrMainFrame());
}
//-------------------------------------------------------------------------------
// WebView::closePluginPlayer
//-------------------------------------------------------------------------------
void WebView::closePluginPlayer()
{
// stop playing
m_pluginplayer->stop();
MakeVisible( ETrue );
delete m_pluginplayer;
m_pluginplayer = 0;
m_brctl->reportStateChanged(TBrCtlDefs::EStatePluginPlayer, EFalse);
// redraw the control
m_brctl->DrawNow();
}
//-------------------------------------------------------------------------------
// WebView::createWidgetExtension
//-------------------------------------------------------------------------------
CWidgetExtension* WebView::createWidgetExtension(MWidgetCallback &aWidgetCallback)
{
if (!m_widgetextension) {
m_widgetextension = CWidgetExtension::NewL(*this, aWidgetCallback);
#if USE(LOW_BANDWIDTH_DISPLAY)
m_page->mainFrame()->loader()->setUseLowBandwidthDisplay(false);
#endif
}
//Widgets dont need memory cache for dead objects. hence set it to 0
cache()->setCapacities(0, 0, 0);
return m_widgetextension;
}
//-------------------------------------------------------------------------------
// WebView::forceLayoutAndResize
//-------------------------------------------------------------------------------
void WebView::forceLayoutAndResize(WebFrame* frame)
{
if (frame) {
Frame* f = core(frame);
FrameView* v = f->view();
Document* doc = f->document();
if (v && doc) {
Node* node = doc;
while (node) {
if (node->renderer()) {
node->renderer()->setNeedsLayoutAndPrefWidthsRecalc();
RenderStyle* style = node->renderer()->style();
if (style) {
RenderStyle* newstyle = new (node->renderer()->renderArena()) RenderStyle(*style);
node->renderer()->setStyle(newstyle);
}
}
node = node->traverseNextNode();
}
f->document()->recalcStyle(Node::Force);
v->setNeedsLayout();
v->layout();
}
}
}
//-------------------------------------------------------------------------------
// WebView::showZoomSliderL
//-------------------------------------------------------------------------------
void WebView::showZoomSliderL()
{
if ( !inPageViewMode()) {
m_pageZoomHandler->showZoomSliderL();
if ( m_repainttimer->IsActive())
{
m_repainttimer->Cancel();
}
}
m_startZoomLevel = m_currentZoomLevel;
}
//-------------------------------------------------------------------------------
// WebView::hideZoomSliderL
//-------------------------------------------------------------------------------
void WebView::hideZoomSliderL()
{
if ( !inPageViewMode()) {
m_pageZoomHandler->hideZoomSliderL();
}
}
//-------------------------------------------------------------------------------
// WebView::notifyZoomSliderModeChangeL
//-------------------------------------------------------------------------------
void WebView::notifyZoomSliderModeChangeL( bool mode )
{
m_dirtyZoomMode = false;
clearOffScreenBitmap();
zoomLevelChanged( m_currentZoomLevel );
m_brctl->reportStateChanged(TBrCtlDefs::EStateZoomSliderMode, mode );
}
//-------------------------------------------------------------------------------
// WebView::maxZoomLevel
//-------------------------------------------------------------------------------
int WebView::maxZoomLevel()
{
return m_maxZoomLevel;
}
//-------------------------------------------------------------------------------
// WebView::minZoomLevel
//-------------------------------------------------------------------------------
int WebView::minZoomLevel()
{
return m_minZoomLevel;
}
//-------------------------------------------------------------------------------
// WebView::updateZoomLevel
//-------------------------------------------------------------------------------
void WebView::updateZoomLevel( TBrCtlDefs::TBrCtlSettings setting, unsigned int value)
{
switch( setting ) {
case TBrCtlDefs::ESettingsZoomLevelMax:
{
if (value != m_maxZoomLevel)
{
//maxzoomlevel is different, needs to reset the zoom
m_maxZoomLevel = value;
UpdateZoomArray();
}
}
break;
case TBrCtlDefs::ESettingsZoomLevelDefault:
m_scrollingSpeed = KNormalScrollRange*100/scalingFactor();
break;
default:
break; // should not occur
}
}
//-------------------------------------------------------------------------------
// WebView::EnterFullscreenBrowsingL
//-------------------------------------------------------------------------------
void WebView::EnterFullscreenBrowsingL()
{
if (m_pageFullScreenHandler) {
m_pageFullScreenHandler->showEscBtnL();
StaticObjectsContainer::instance()->setFullScreenMode(true);
}
}
//-------------------------------------------------------------------------------
// WebView::LeaveFullscreenBrowsingL
//-------------------------------------------------------------------------------
void WebView::LeaveFullscreenBrowsingL()
{
if (m_pageFullScreenHandler) {
m_pageFullScreenHandler->hideEscBtnL();
StaticObjectsContainer::instance()->setFullScreenMode(false);
}
}
//-------------------------------------------------------------------------------
// WebView::nootifyFullscreenModeChangeL
//-------------------------------------------------------------------------------
void WebView::notifyFullscreenModeChangeL(bool mode)
{
if (m_pageFullScreenHandler )
m_brctl->reportStateChanged(TBrCtlDefs::EStateFullscreenBrowsing, mode );
}
//-------------------------------------------------------------------------------
// WebView::checkForZoomChange
//-------------------------------------------------------------------------------
void WebView::checkForZoomChange()
{
zoomLevelChanged(m_currentZoomLevel);
}
void WebView::activateVirtualKeyboard()
{
if (isEditable() && iCoeEnv->Fep()) {
fepTextEditor()->CancelEditingMode();
fepTextEditor()->UpdateEditingMode();
iCoeEnv->Fep()->HandleChangeInFocus();
fepTextEditor()->ActivatePenInputRequest();
}
}
void WebView::Stop()
{
mainFrame()->stopLoading();
}
void WebView::synchRequestPending(bool flag)
{
m_synchRequestPending = flag;
// TODO - nl - Disabled for now - there's no cursor in S60 5.0 release
//WebCursor* cursor = StaticObjectsContainer::instance()->webCursor();
if (flag) {
m_brctl->reportStateChanged(TBrCtlDefs::EStateSynchRequestMode, ETrue);
//cursor->setWaitCursor(ETrue);
if (AknLayoutUtils::PenEnabled()) {
// Disable (block) pointer events
DrawableWindow()->SetPointerGrab(EFalse);
}
}
else {
if (AknLayoutUtils::PenEnabled()) {
// Reenable pointer events
DrawableWindow()->SetPointerGrab(ETrue);
}
//cursor->setWaitCursor(EFalse);
m_brctl->reportStateChanged(TBrCtlDefs::EStateSynchRequestMode, EFalse);
}
}
void WebView::setHistoryLoad(bool value) {
m_historyLoad = value;
}
void WebView::setRedirectWithLockedHistory(bool value) {
m_redirectWithLockedHistory = value;
}
void WebView::setFastScrollingMode(bool fastScrolling)
{
if (fastScrolling != m_viewIsFastScrolling) {
setViewIsFastScrolling (fastScrolling);
m_isPluginsVisible = false;
mainFrame()->makeVisiblePlugins(!m_viewIsFastScrolling);
m_isPluginsVisible = !m_viewIsFastScrolling;
if (!m_viewIsFastScrolling) {
mainFrame()->notifyPluginsOfScrolling();
}
toggleRepaintTimer(!m_viewIsFastScrolling);
}
}
void WebView::toggleRepaintTimer(bool on)
{
if ( m_repainttimer->IsActive()) {
m_repainttimer->Cancel();
}
if (on) {
m_repainttimer->Start(0, 0, TCallBack( &doRepaintCb, this ) );
}
m_allowRepaints = on;
}
//-----------------------------------------------------------------------------
// WebView::setZoomCursorPosition
// Set the cursor position while zooming, this is only for non-touch device
//-----------------------------------------------------------------------------
void WebView::setZoomCursorPosition(TBool isZoomIn)
{
int zoomLevel = m_currentZoomLevel;
TInt index = FindCurrentZoomIndex(m_currentZoomLevel);
if (index == -1)
{
//Shouldn't happen -- do nothing
return;
}
if (isZoomIn && index <=m_zoomLevelArray.Count()-2)
{
index++;
zoomLevel = m_zoomLevelArray[index];
}
else if (!isZoomIn && index > 0 )
{
index--;
zoomLevel = m_zoomLevelArray[index];
}
// move the content
WebFrameView* view = mainFrame()->frameView();
if (!view) return;
WebCursor* cursor = StaticObjectsContainer::instance()->webCursor();
if (cursor) {
TPoint pt = cursor->position();
int z = zoomLevel * 100 / m_currentZoomLevel;
int xOff = (pt.iX * z / 100 - pt.iX)*100/zoomLevel;
int yOff = (pt.iY * z / 100 - pt.iY)*100/zoomLevel;
TPoint cp = view->contentPos();
cp += TPoint(xOff, yOff);
view->setContentPos(cp);
}
//setZoomLevel(zoomLevel);
mainFrame()->notifyPluginsOfScrolling();
}
// ---------------------------------------------------------------------------
// WebView::FindCurrentZoomIndex
// ---------------------------------------------------------------------------
TInt WebView::FindCurrentZoomIndex(TInt aCurrentZoomLevel)
{
TInt aIndex = -1;
for (aIndex=0; aIndex<m_zoomLevelArray.Count()-1; aIndex++)
{
TInt tmpZoomLevel = m_zoomLevelArray[aIndex];
if (aCurrentZoomLevel == m_zoomLevelArray[aIndex] )
{
break;
}
}
return aIndex;
}
TInt WebView::getWidgetId()
{
return m_widgetextension ? m_widgetextension->GetWidgetId():0;
}
void WebView::setShowCursor(TBool showCursor)
{
m_showCursor = showCursor;
StaticObjectsContainer::instance()->webCursor()->setCursorVisible(showCursor);
}
void WebView::focusedElementChanged(Element* element)
{
Frame* frame = element->document()->frame();
WebFrameView* fv = kit(frame)->frameView();
if (m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeTabbed || m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeNone) {
if (!element || !element->document() ||!element->renderer()) return;
if (element->hasTagName(textareaTag) || (element->hasTagName(inputTag) && (reinterpret_cast<HTMLInputElement*>(element))->isTextField())) {
TPoint point = TRect(element->getRect()).iTl;
point = fv->frameCoordsInViewCoords(point);
StaticObjectsContainer::instance()->webCursor()->setPosition(point);
TPointerEvent event;
event.iPosition = StaticObjectsContainer::instance()->webCursor()->position();
event.iModifiers = 0;
event.iType = TPointerEvent::EMove;
core(mainFrame())->eventHandler()->handleMouseMoveEvent(PlatformMouseEvent(event));
}
else {
int x, y;
element->renderer()->absolutePosition(x, y);
Vector<IntRect> rects;
element->renderer()->absoluteRects(rects, x, y);
TPoint point;
if (rects.size() > 0) {
point = TPoint(rects[0].x(), rects[0].y());
point = fv->frameCoordsInViewCoords(point);
StaticObjectsContainer::instance()->webCursor()->setPosition(point);
TPointerEvent event;
event.iPosition = StaticObjectsContainer::instance()->webCursor()->position();
event.iModifiers = 0;
event.iType = TPointerEvent::EMove;
core(mainFrame())->eventHandler()->handleMouseMoveEvent(PlatformMouseEvent(event));
}
}
if (m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeTabbed) {
m_tabbedNavigation->focusedElementChanged(element);
}
// onload event on the first page could happen before the view becomes visible
m_savedCursorPosition = StaticObjectsContainer::instance()->webCursor()->position();
m_focusedElementType = nodeTypeB(element, frame);
}
}
void WebView::windowObjectCleared() const
{
if (m_widgetextension) {
WebView* that = const_cast<WebView*>(this);
that->m_widgetextension->windowObjectCleared();
}
}
// END OF FILE