webengine/osswebengine/WebKit/s60/webview/WebCursor.cpp
changeset 0 dd21522fd290
child 1 7c90e6132015
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   Implemetation of CWebKiCursor
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "config.h"
       
    20 #include "../../bidi.h"
       
    21 #include <stdlib.h>
       
    22 #include "StaticObjectsContainer.h"
       
    23 #include "WebView.h"
       
    24 #include "WebFrame.h"
       
    25 #include "WebFrameView.h"
       
    26 #include "WebFrameBridge.h"
       
    27 #include "Frame.h"
       
    28 #include "Document.h"
       
    29 #include "Node.h"
       
    30 #include "Element.h"
       
    31 #include "HTMLImageElement.h"
       
    32 #include "RenderImage.h"
       
    33 #include "BrCtl.h"
       
    34 #include "HTMLNames.h"
       
    35 #include "HTMLElement.h"
       
    36 #include "MouseEvent.h"
       
    37 #include "EventNames.h"
       
    38 #include "WebUtil.h"
       
    39 #include "SettingsContainer.h"
       
    40 #include "WebCursor.h"
       
    41 #include "Page.h"
       
    42 #include "FocusController.h"
       
    43 #include <AknUtils.h>
       
    44 #include "PlatformScrollbar.h"
       
    45 
       
    46 #include "eikon.hrh"
       
    47 
       
    48 
       
    49 const int KMiddleStep = 8;
       
    50 const int KFlipAdjust =12;
       
    51 const int KCursorIncremental = 17;         // 17 pixels
       
    52 const int KTransparencyTime = 8000*1000; //8s
       
    53 const int KTransparencyMoveThreshold = 15;
       
    54 
       
    55 const int KAggressiveSearch = 50;
       
    56 
       
    57 #define KCursorOffset TPoint(-3,-4)
       
    58 
       
    59 using namespace WebCore;
       
    60 using namespace EventNames;
       
    61 using namespace HTMLNames;
       
    62 
       
    63 // ============================= LOCAL FUNCTIONS ===============================
       
    64 
       
    65 inline IntPoint nearestPointInRect(const IntPoint &point, const IntRect &rect)
       
    66 {
       
    67   //Error condition
       
    68   if (rect.isEmpty()) return IntPoint(0,0);
       
    69 
       
    70   int y = std::max(rect.y(), std::min(rect.bottom(), point.y()));
       
    71   int x = std::max(rect.x(), std::min(rect.right(), point.x()));
       
    72 
       
    73   return IntPoint(x,y);
       
    74 }
       
    75 
       
    76 TInt TransparencyTimerCb(TAny* any)
       
    77     {
       
    78     WebCursor* c = static_cast<WebCursor*>(any);
       
    79     c->setTransparent(true);
       
    80     return EFalse;
       
    81     }
       
    82 
       
    83 // ============================ MEMBER FUNCTIONS ===============================
       
    84 
       
    85 // -----------------------------------------------------------------------------
       
    86 // CWebKitCursor::NewL
       
    87 // Two-phased constructor.
       
    88 // -----------------------------------------------------------------------------
       
    89 WebCursor* WebCursor::NewL()
       
    90     {
       
    91     WebCursor* self = new (ELeave) WebCursor();
       
    92     CleanupStack::PushL( self );
       
    93     self->ConstructL();
       
    94     CleanupStack::Pop();
       
    95     return self;
       
    96     }
       
    97 
       
    98 // -----------------------------------------------------------------------------
       
    99 // WebCursor::WebCursor
       
   100 // Constructor.
       
   101 // -----------------------------------------------------------------------------
       
   102 WebCursor::WebCursor() :
       
   103         m_pos(TPoint(KInitialOffset,KInitialOffset))
       
   104       , m_previousLr(0)
       
   105       , m_previousTb(0)
       
   106       , m_view(0)
       
   107       , m_visible(true)
       
   108       , m_flipcounter(0)
       
   109       , m_type(PointerCursor)
       
   110       , m_flipCounter(0)
       
   111     {
       
   112     }
       
   113 
       
   114 // -----------------------------------------------------------------------------
       
   115 // WebCursor::~WebCursor
       
   116 // Deconstructor.
       
   117 // -----------------------------------------------------------------------------
       
   118 WebCursor::~WebCursor()
       
   119     {
       
   120     m_sprite.Close();
       
   121     delete m_transarrowmask;
       
   122     delete m_transtimer;
       
   123     }
       
   124 
       
   125 // -----------------------------------------------------------------------------
       
   126 // WebCursor::ConstructL
       
   127 // -----------------------------------------------------------------------------
       
   128 void WebCursor::ConstructL()
       
   129     {
       
   130     m_transtimer = CPeriodic::NewL(CActive::EPriorityStandard);
       
   131     m_visible = !AknLayoutUtils::PenEnabled();
       
   132     }
       
   133 
       
   134 // -----------------------------------------------------------------------------
       
   135 // WebCursor::SetCurrentView
       
   136 // -----------------------------------------------------------------------------
       
   137 void WebCursor::setCurrentView(WebView& view)
       
   138     {
       
   139     if (!m_view)
       
   140     {
       
   141         m_view = &view;
       
   142         constructSprite();
       
   143     }
       
   144     m_view = &view;
       
   145     setOpaqueUntil(KTransparencyTime);
       
   146     m_transcount = 0;
       
   147     }
       
   148 
       
   149 // -----------------------------------------------------------------------------
       
   150 // WebCursor::ConstructSprite
       
   151 // -----------------------------------------------------------------------------
       
   152 void WebCursor::constructSprite()
       
   153     {
       
   154 
       
   155     //tot:fixme
       
   156     m_arrow = StaticObjectsContainer::instance()->webCannedImages()->getImage(WebCannedImages::EImageArrowBitmap);
       
   157     m_hand = StaticObjectsContainer::instance()->webCannedImages()->getImage(WebCannedImages::EImageFingerBitmap);
       
   158     m_ibeam = StaticObjectsContainer::instance()->webCannedImages()->getImage(WebCannedImages::EImageIBeam);
       
   159     m_selectMulti = StaticObjectsContainer::instance()->webCannedImages()->getImage(WebCannedImages::EImageSelectMulti);
       
   160     //iSmartLinkPhoneImage = StaticObjectsContainer::instance()->webCannedImages()->getImage(WebCannedImages::EImageSmartLinkPhone);
       
   161     //iSmartLinkEmailImage = StaticObjectsContainer::instance()->webCannedImages()->getImage(WebCannedImages::EImageSmartLinkEmail);
       
   162     m_wait = StaticObjectsContainer::instance()->webCannedImages()->getImage(WebCannedImages::EImageWaitArrowBitmap);
       
   163     TSize s = m_arrow.m_msk->SizeInPixels();
       
   164     m_transarrowmask = new (ELeave) CFbsBitmap();
       
   165     m_transarrowmask->Create(s,m_arrow.m_msk->DisplayMode());
       
   166     CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(m_transarrowmask);
       
   167     CleanupStack::PushL(dev);
       
   168     CFbsBitGc* gc;
       
   169     User::LeaveIfError(dev->CreateContext(gc));
       
   170     gc->BitBlt(TPoint(0,0),m_arrow.m_msk);
       
   171     m_transarrowmask->LockHeap();
       
   172     TUint8* data = (TUint8*)m_transarrowmask->DataAddress();
       
   173     TUint8* end = data + s.iWidth*s.iHeight;
       
   174     // divide all pixels by 3
       
   175     while ( data<end )
       
   176         {
       
   177         *(data++) /= 3;
       
   178         }
       
   179     m_transarrowmask->UnlockHeap();
       
   180     delete gc;
       
   181     CleanupStack::PopAndDestroy();
       
   182     /////////////////////////////////
       
   183     m_sprite = RWsSprite(m_view->ControlEnv()->WsSession());
       
   184     RWindowTreeNode *window =  (RDrawableWindow* )m_view->brCtl()->CCoeControlParent()->DrawableWindow();
       
   185     m_sprite.Construct(*window,TPoint(KInitialOffset,KInitialOffset),ESpriteNoChildClip);
       
   186 
       
   187     TSpriteMember spriteMem;
       
   188     spriteMem.iBitmap = 0;
       
   189     spriteMem.iMaskBitmap = 0;
       
   190     spriteMem.iInvertMask = ETrue;
       
   191 
       
   192     m_sprite.AppendMember(spriteMem);
       
   193     m_sprite.Activate();
       
   194     }
       
   195 
       
   196 // -----------------------------------------------------------------------------
       
   197 // WebCursor::CursorUpdate
       
   198 // -----------------------------------------------------------------------------
       
   199 void WebCursor::setCursor(CursorTypes type)
       
   200 {
       
   201     m_sprite.SetPosition( m_pos );
       
   202     m_type = type;
       
   203     if (m_visible) {
       
   204         TSpriteMember spriteMem;
       
   205         switch( type )
       
   206             {
       
   207             case PointerCursor:
       
   208             default:
       
   209                 {
       
   210                 spriteMem.iBitmap = m_waiton ? m_wait.m_img : m_arrow.m_img;
       
   211                 spriteMem.iMaskBitmap = m_waiton ? m_wait.m_img :
       
   212                     (m_transparent && m_transcount > KTransparencyMoveThreshold ? m_transarrowmask : m_arrow.m_msk);
       
   213                 break;
       
   214                 }
       
   215            case HandCursor:
       
   216                 {
       
   217                 spriteMem.iBitmap = m_hand.m_img;
       
   218                 spriteMem.iMaskBitmap = m_hand.m_msk;
       
   219                 break;
       
   220                 }
       
   221            case IBeamCursor:
       
   222                 {
       
   223                /*tot:fixme if ( m_view->FocusedElementType() == TBrCtlDefs::EElementSmartLinkTel )
       
   224                     {
       
   225                     spriteMem.iBitmap = iSmartLinkPhoneImage.m_img;
       
   226                     spriteMem.iMaskBitmap = iSmartLinkPhoneImage.m_msk;
       
   227                     }
       
   228                 else if ( m_view->FocusedElementType() == TBrCtlDefs::EElementSmartLinkEmail )
       
   229                     {
       
   230                     spriteMem.iBitmap = iSmartLinkEmailImage.m_img;
       
   231                     spriteMem.iMaskBitmap = iSmartLinkEmailImage.m_msk;
       
   232                     }
       
   233                 else*/
       
   234                     {
       
   235                     spriteMem.iBitmap = m_ibeam.m_img;
       
   236                     spriteMem.iMaskBitmap = m_ibeam.m_msk;
       
   237                     }
       
   238                 break;
       
   239                 }
       
   240            case SelectMultiCursor:
       
   241                {
       
   242                     spriteMem.iBitmap = m_selectMulti.m_img;
       
   243                     spriteMem.iMaskBitmap = m_selectMulti.m_msk;
       
   244                     break;
       
   245                }
       
   246             }
       
   247         spriteMem.iOffset = KCursorOffset;
       
   248         spriteMem.iInvertMask = ETrue;
       
   249         m_sprite.UpdateMember( 0, spriteMem );
       
   250     } else {
       
   251         TSpriteMember spriteMem;
       
   252         spriteMem.iBitmap = 0;
       
   253         spriteMem.iMaskBitmap = 0;
       
   254         spriteMem.iInvertMask = ETrue;
       
   255         m_sprite.UpdateMember( 0, spriteMem );
       
   256     }
       
   257 }
       
   258 
       
   259 // -----------------------------------------------------------------------------
       
   260 // WebCursor::CursorUpdate
       
   261 // -----------------------------------------------------------------------------
       
   262 void WebCursor::cursorUpdate(bool visible)
       
   263 {
       
   264     if (!m_view || !m_view->brCtl()->settings())
       
   265         return;
       
   266     if ( m_view->showCursor() ) {
       
   267         m_visible = visible && (!m_view->brCtl()->settings()->getTabbedNavigation() || m_view->focusedElementType() == TBrCtlDefs::EElementSelectMultiBox); // check for tabbedNavigation here because it is called from so many places.
       
   268     }
       
   269     
       
   270     resetTransparency();
       
   271     CursorTypes type = PointerCursor;
       
   272     TBrCtlDefs::TBrCtlElementType elType = m_view->focusedElementType();
       
   273     if (m_visible) {
       
   274         if (elType == TBrCtlDefs::EElementNone || elType == TBrCtlDefs::EElementBrokenImage)
       
   275             type = PointerCursor;
       
   276         else if (elType == TBrCtlDefs::EElementSmartLinkTel || elType == TBrCtlDefs::EElementSmartLinkEmail)
       
   277             type = IBeamCursor;
       
   278         else if (m_view->brCtl()->settings()->getTabbedNavigation() && elType == TBrCtlDefs::EElementSelectMultiBox)
       
   279             type = SelectMultiCursor;
       
   280         else
       
   281             type = HandCursor;
       
   282     }
       
   283     setCursor(type);
       
   284 }
       
   285 
       
   286 
       
   287 
       
   288 // -----------------------------------------------------------------------------
       
   289 // CWebKitCursor::getFrameAtPoint
       
   290 // -----------------------------------------------------------------------------
       
   291 WebFrame* WebCursor::getFrameAtPoint(const TPoint& viewPos_)
       
   292     {
       
   293     if (!m_view)
       
   294         return 0;
       
   295     WebFrame* frameAtPoint = m_view->mainFrame()->frameAtPoint(viewPos_);
       
   296     if (!frameAtPoint)
       
   297         frameAtPoint = m_view->mainFrame();
       
   298     return frameAtPoint;
       
   299     }
       
   300 
       
   301 // -----------------------------------------------------------------------------
       
   302 // WebCursor::Reset
       
   303 // -----------------------------------------------------------------------------
       
   304 void WebCursor::reset()
       
   305     {
       
   306     m_view->setFocusedElementType(TBrCtlDefs::EElementNone);
       
   307     cursorUpdate(true);
       
   308     m_nodeRect = TRect();
       
   309     }
       
   310 
       
   311 // -----------------------------------------------------------------------------
       
   312 // WebCursor::SetWaitCursor
       
   313 // -----------------------------------------------------------------------------
       
   314 void WebCursor::setWaitCursor(bool waiton)
       
   315     {
       
   316     m_waiton = waiton;
       
   317     if (m_waiton)
       
   318         setCursor(PointerCursor);
       
   319     else
       
   320         cursorUpdate(m_visible);
       
   321     }
       
   322 
       
   323 // -----------------------------------------------------------------------------
       
   324 // WebCursor::OffsetCursor
       
   325 // -----------------------------------------------------------------------------
       
   326 void WebCursor::offsetCursor(const TPoint& offset)
       
   327     {
       
   328     m_pos -= offset;
       
   329     m_nodeRect.Move(-offset.iX,-offset.iY);
       
   330     }
       
   331 
       
   332 // -----------------------------------------------------------------------------
       
   333 // WebCursor::SetTransparent
       
   334 // -----------------------------------------------------------------------------
       
   335 void WebCursor::setTransparent(bool transparent)
       
   336 {
       
   337     if (transparent)
       
   338         m_transtimer->Cancel();
       
   339     if (m_transparent != transparent) {
       
   340         m_transparent = transparent;
       
   341         // only pointer cursor is transparent
       
   342         if (m_transparent && m_view->focusedElementType() == TBrCtlDefs::EElementNone)
       
   343             setCursor(PointerCursor);
       
   344         else
       
   345             cursorUpdate(m_visible);
       
   346     }
       
   347 }
       
   348 
       
   349 // -----------------------------------------------------------------------------
       
   350 // WebCursor::SetOpaqueUntil
       
   351 // -----------------------------------------------------------------------------
       
   352 void WebCursor::setOpaqueUntil(int microsecs)
       
   353     {
       
   354     setTransparent(false);
       
   355     m_transtimer->Cancel();
       
   356     m_transtimer->Start(microsecs,0,TCallBack(TransparencyTimerCb,this));
       
   357     }
       
   358 
       
   359 // -----------------------------------------------------------------------------
       
   360 // WebCursor::IncreaseTransparencyMoveCount
       
   361 // -----------------------------------------------------------------------------
       
   362 void WebCursor::increaseTransparencyMoveCount()
       
   363     {
       
   364     ++m_transcount;
       
   365     }
       
   366 
       
   367 // -----------------------------------------------------------------------------
       
   368 // WebCursor::ResetTransparency
       
   369 // -----------------------------------------------------------------------------
       
   370 void WebCursor::resetTransparency()
       
   371     {
       
   372     m_transcount = 0;
       
   373     setOpaqueUntil(KTransparencyTime);
       
   374     }
       
   375 
       
   376 //-------------------------------------------------------------------------------
       
   377 // WebCursor::innerRect()
       
   378 //-------------------------------------------------------------------------------
       
   379 void WebCursor::innerRect(TRect& rect)
       
   380 {
       
   381   TPoint c = rect.Center();
       
   382   int z = m_view->scalingFactor();
       
   383   int dx = KCursorIncremental * z / 100;
       
   384   int dy = KCursorIncremental * z / 100;
       
   385 
       
   386   dx = Max(dx, 2 * rect.Width() / 5);
       
   387   dy = Max(dy, 2 * rect.Height() / 5);
       
   388 
       
   389   rect.Shrink(dx, dy);
       
   390 
       
   391   if (!rect.IsNormalized()) {
       
   392     rect.SetRect(c, c);
       
   393   }
       
   394 }
       
   395 
       
   396 //-------------------------------------------------------------------------------
       
   397 // WebCursor::frameHasContentToScroll()
       
   398 //-------------------------------------------------------------------------------
       
   399 bool WebCursor::frameHasContentToScroll(WebFrame* frame, TPoint& delta)
       
   400 {
       
   401     WebFrameView* rfv = frame->frameView();
       
   402     TPoint contentpos = rfv->contentPos();
       
   403     TSize contentsize = rfv->contentSize();
       
   404     bool hasContentToScrollY = false;
       
   405     bool hasContentToScrollX = false;
       
   406 
       
   407     if (delta.iY > 0)
       
   408         {
       
   409         hasContentToScrollY = (contentpos.iY < (contentsize.iHeight - rfv->rect().Height()));
       
   410         }
       
   411     else if (delta.iY < 0)
       
   412         {
       
   413         hasContentToScrollY = (contentpos.iY > 0);
       
   414         }
       
   415 
       
   416     if (delta.iX > 0)
       
   417         {
       
   418         hasContentToScrollX = (contentpos.iX < (contentsize.iWidth - rfv->rect().Width()));
       
   419         }
       
   420     else if (delta.iX < 0)
       
   421         {
       
   422         hasContentToScrollX = (contentpos.iX > 0);
       
   423         }
       
   424 
       
   425     return hasContentToScrollY || hasContentToScrollX;
       
   426 
       
   427 }
       
   428 
       
   429 //-------------------------------------------------------------------------------
       
   430 // WebCursor::determineScrollingFrame()
       
   431 //-------------------------------------------------------------------------------
       
   432 WebFrame*  WebCursor::determineScrollingFrame(int border1, int border2, int pos,
       
   433                                               WebFrame* fr1, WebFrame* fr2, TPoint& delta)
       
   434 {
       
   435   WebFrame* ret = NULL;
       
   436 
       
   437   if (pos < border1 && pos < border2) return ret; //"magic" line has not been reached
       
   438   if (pos >= border1 && pos >= border2) {
       
   439       if (border1 > border2) {
       
   440           ret = frameHasContentToScroll(fr2, delta) ? fr2 : fr1;
       
   441       }
       
   442       else {
       
   443           ret = frameHasContentToScroll(fr1, delta) ? fr1 : fr2;
       
   444       }
       
   445   }
       
   446   else if (border1 <= pos && pos <= border2) {//"magic" line of fr1 was hit first
       
   447       ret = fr1;
       
   448   }
       
   449   else if (border2 <= pos && pos <= border1) {//"magic" line of fr2 was hit first
       
   450       ret = fr2;
       
   451   }
       
   452   return ret;
       
   453 }
       
   454 
       
   455 
       
   456 //-------------------------------------------------------------------------------
       
   457 // WebCursor::calculateScrollableFrameView()
       
   458 // TODO: Investigate diagonal events, especially in the light of IFrames.
       
   459 //-------------------------------------------------------------------------------
       
   460 WebFrame* WebCursor::calculateScrollableFrameView(TPoint& pos, TPoint& delta, TRect& fRect, bool autoscroll)
       
   461 {
       
   462   WebFrame* frame = getFrameAtPoint(pos);
       
   463   WebFrame* ret_frame = NULL;
       
   464   WebFrameView* mfView = m_view->mainFrame()->frameView();
       
   465   TPoint docContPos = mfView->toViewCoords(mfView->contentPos());
       
   466   int z = m_view->scalingFactor();
       
   467   m_incrLimit.iX = Abs(delta.iX) * 2 * z / 100;
       
   468   m_incrLimit.iY = Abs(delta.iY) * 2 * z / 100;
       
   469 
       
   470 
       
   471   for (; frame; frame = frame->parentFrame())  {
       
   472     bool hScroll = frame->frameView()->hScrollbar()->isEnabled();
       
   473     bool vScroll = frame->frameView()->vScrollbar()->isEnabled();
       
   474           // Dont scroll a frameset
       
   475     if (frame->parentFrame() && frame->parentFrame()->isFrameSet()) {
       
   476       continue;
       
   477     }
       
   478     else if (frame->parentFrame() && !hScroll && !vScroll) {
       
   479       continue;
       
   480     }
       
   481     else if (!frame->parentFrame()) { //main view
       
   482       hScroll = true;
       
   483       vScroll = true;
       
   484     }
       
   485 
       
   486 
       
   487     WebFrame*  pf = frame->parentFrame() ? frame->parentFrame() : m_view->mainFrame();
       
   488     WebFrameView* pfv = pf->frameView();
       
   489     WebFrameView* ppfv = pf->parentFrame() ? pf->parentFrame()->frameView() : NULL;
       
   490     TRect pfRect = pfv->rect();
       
   491     if (ppfv) {// parent frame is not a main frame
       
   492         pfRect = TRect(ppfv->frameCoordsInViewCoords(pfRect.iTl),
       
   493                           ppfv->frameCoordsInViewCoords(pfRect.iBr));
       
   494     }
       
   495 
       
   496     WebFrameView* fv = frame->frameView();
       
   497     TRect framerect = fv ->rect();
       
   498     if (frame->parentFrame()) {// frame is not a main frame
       
   499        framerect = TRect(pfv->frameCoordsInViewCoords(framerect.iTl),
       
   500                          pfv->frameCoordsInViewCoords(framerect.iBr));
       
   501     }
       
   502 
       
   503     TRect pfInnerRect = pfRect;
       
   504     innerRect(pfInnerRect);
       
   505     TRect fInnerRect = framerect;
       
   506     innerRect(fInnerRect);
       
   507 
       
   508 
       
   509     // See which "magic" line we crossed first
       
   510     if (delta.iY > 0) {  //scroll down.
       
   511         ret_frame = determineScrollingFrame(pfInnerRect.iBr.iY, fInnerRect.iBr.iY, pos.iY, pf, frame, delta);
       
   512         m_incrLimit.iY = Min (m_incrLimit.iY, Abs(framerect.iBr.iY - pos.iY));
       
   513     }
       
   514     else if (delta.iY < 0) { //scroll up.
       
   515         ret_frame = determineScrollingFrame(-pfInnerRect.iTl.iY, -fInnerRect.iTl.iY, -pos.iY, pf, frame, delta);
       
   516         m_incrLimit.iY = Min (m_incrLimit.iY, Abs(pos.iY - framerect.iTl.iY));
       
   517     }
       
   518 
       
   519     if (delta.iX > 0) {
       
   520         ret_frame = determineScrollingFrame(pfInnerRect.iBr.iX, fInnerRect.iBr.iX, pos.iX, pf, frame, delta);
       
   521         m_incrLimit.iX = Min (m_incrLimit.iX, Abs(framerect.iBr.iX - pos.iX));
       
   522     }
       
   523     else if (delta.iX < 0) {
       
   524         ret_frame = determineScrollingFrame(-pfInnerRect.iTl.iX, -fInnerRect.iTl.iX, -pos.iX, pf, frame, delta);
       
   525         m_incrLimit.iX = Min (m_incrLimit.iX, Abs(pos.iX - framerect.iTl.iX));
       
   526     }
       
   527 
       
   528     fRect = (ret_frame == frame) ? framerect : pfRect;
       
   529 
       
   530      if (ret_frame) {
       
   531         if (!ret_frame->parentFrame()) {
       
   532                 m_incrLimit.iX = Abs(delta.iX) * 2 * z / 100;
       
   533                 m_incrLimit.iY = Abs(delta.iY) * 2 * z / 100;
       
   534         }
       
   535 
       
   536         if (!frameHasContentToScroll(ret_frame, delta)) {
       
   537             ret_frame = NULL;
       
   538             m_incrLimit.iX = KCursorIncremental * z / 100;
       
   539             m_incrLimit.iY = KCursorIncremental * z / 100;
       
   540         }
       
   541 
       
   542         if (ret_frame) {
       
   543             m_incrLimit.iX = Max(m_incrLimit.iX, KMiddleStep);
       
   544             m_incrLimit.iY = Max(m_incrLimit.iY, KMiddleStep);
       
   545             break;
       
   546         }
       
   547     }
       
   548     else {
       
   549          m_incrLimit.iX = Abs(delta.iX) * 2 * z / 100;
       
   550          m_incrLimit.iY = Abs(delta.iY) * 2 * z / 100;
       
   551     }
       
   552   }
       
   553 
       
   554   return ret_frame;
       
   555 }
       
   556 
       
   557 
       
   558 //-------------------------------------------------------------------------------
       
   559 // Method that scrolls and moves the cursor based on the navigation algorithm
       
   560 // TODO: Investigate "autoscroll" and diagonal events from real HW and the
       
   561 //       diagonal event simulator wedge.
       
   562 //-------------------------------------------------------------------------------
       
   563 void WebCursor::scrollAndMoveCursor(int dir, int scrollRange, bool autoscroll)
       
   564 {
       
   565     if (!m_view)
       
   566         return;
       
   567 
       
   568     int lr = 0;
       
   569     int tb = 0;
       
   570     int deltaX;
       
   571     int deltaY;
       
   572 
       
   573     switch (dir)
       
   574       {
       
   575 
       
   576         case EKeyUpArrow:             // North
       
   577           tb = -1;
       
   578           break;
       
   579 
       
   580         case EKeyRightUpArrow:        // Northeast
       
   581         case EStdKeyDevice11:         //   : Extra KeyEvent supports diagonal event simulator wedge
       
   582           tb = -1;
       
   583           lr = +2;                    // Make it run closer to 45 degrees
       
   584           break;
       
   585 
       
   586         case EKeyRightArrow:          // East
       
   587           lr = +1;
       
   588           break;
       
   589 
       
   590         case EKeyRightDownArrow:      // Southeast
       
   591         case EStdKeyDevice12:         //   : Extra KeyEvent supports diagonal event simulator wedge
       
   592           tb = +1;
       
   593           lr = +2;
       
   594           break;
       
   595 
       
   596         case EKeyDownArrow:           // South
       
   597           tb = +1;
       
   598           break;
       
   599 
       
   600         case EKeyLeftDownArrow:       // Southwest
       
   601         case EStdKeyDevice13:         //   : Extra KeyEvent supports diagonal event simulator wedge
       
   602           tb = +1;
       
   603           lr = -2;
       
   604           break;
       
   605 
       
   606         case EKeyLeftArrow:           // West
       
   607           lr = -1;
       
   608           break;
       
   609 
       
   610         case EKeyLeftUpArrow:         // Northwest
       
   611         case EStdKeyDevice10:         //   : Extra KeyEvent supports diagonal event simulator wedge
       
   612           tb = -1;
       
   613           lr = -2;
       
   614           break;
       
   615 
       
   616         default:
       
   617           break;
       
   618 
       
   619       }
       
   620 
       
   621     deltaX = lr * scrollRange/2;
       
   622     deltaY = tb * scrollRange;
       
   623 
       
   624     TPoint delta = TPoint(deltaX, deltaY);
       
   625     WebFrame* frame = NULL;
       
   626     WebFrameView* fv = NULL;
       
   627     TPoint oldpos;
       
   628     TRect inRect = TRect();
       
   629     bool needScroll = false;
       
   630 
       
   631     frame = calculateScrollableFrameView(m_pos, delta, inRect, autoscroll);
       
   632     needScroll = (frame != NULL);
       
   633     if (!frame) {
       
   634       frame = m_view->mainFrame();
       
   635     }
       
   636     fv = frame->frameView();
       
   637     oldpos = fv->contentPos();
       
   638 
       
   639     if (autoscroll || m_view->pageView()) {
       
   640         // scroll
       
   641         fv->scrollTo(oldpos + delta);
       
   642 
       
   643         if (!m_view->pageView()) {
       
   644             TPoint cp = position();
       
   645             if (fv->contentPos() == oldpos) {
       
   646                 // not scrolling, move the cursor instead
       
   647                 cp.iX += deltaX;
       
   648                 cp.iY += deltaY;
       
   649             } else {
       
   650                 // move cursor slowly out of the way
       
   651                 cp.iX += deltaX/6;
       
   652                 cp.iY += deltaY/6;
       
   653             }
       
   654             // limit the movement, don't scroll out of the view area
       
   655             if (lr != 0) {
       
   656               cp.iX = (lr < 0) ? Max(inRect.iTl.iX + 8, cp.iX) : Min(inRect.iBr.iX - 8, cp.iX);
       
   657             }
       
   658             if (tb != 0) {
       
   659               cp.iY = (tb < 0) ? Max(inRect.iTl.iY + 8, cp.iY) : Min(inRect.iBr.iY - 8, cp.iY);
       
   660             }
       
   661             if (cp.iX == (inRect.iTl.iX + 8) || (cp.iX == inRect.iBr.iX - 8) ||
       
   662                 (cp.iY == inRect.iTl.iY + 8) || (cp.iY == inRect.iBr.iY - 8)) {
       
   663             }
       
   664             setPosition(cp);
       
   665             reset();
       
   666         }
       
   667         return;
       
   668     }
       
   669     if (!handleSelectElementScrolling(m_view, tb)) {
       
   670         // link snapping
       
   671       moveCursor( lr,tb,scrollRange);
       
   672     }
       
   673 
       
   674     TPoint newpos(oldpos);
       
   675     newpos += TPoint(lr*scrollRange/2, tb*scrollRange);
       
   676     newpos = fv->nearestPointInFrame(newpos);
       
   677 
       
   678     int adjustedScrollRange = Abs(lr*(newpos.iX - oldpos.iX)) + Abs(tb*(newpos.iY - oldpos.iY));
       
   679 
       
   680     if (lr==0)
       
   681         increaseTransparencyMoveCount();
       
   682     else
       
   683         resetTransparency();
       
   684 
       
   685     if (adjustedScrollRange) {
       
   686         TPoint p = position();
       
   687         if ( needScroll ) {
       
   688             innerRect(inRect);
       
   689             int deltax = (lr != 0 ) ? ( (lr > 0) ? (p.iX - inRect.iBr.iX) : (inRect.iTl.iX - p.iX ) ) : 0 ;
       
   690             int deltay = (tb != 0 ) ? ( (tb > 0) ? (p.iY - inRect.iBr.iY ) : (inRect.iTl.iY - p.iY) ) : 0 ;
       
   691             deltax = Min(adjustedScrollRange, deltax);
       
   692             deltay = Min(adjustedScrollRange, deltay);
       
   693             TPoint offset(fv->toViewCoords(TPoint(lr*deltax,tb*deltay)));
       
   694             offsetCursor(offset);
       
   695             fv->scrollTo(oldpos+TPoint(lr*deltax , tb*deltay));
       
   696         } else {
       
   697             if (m_view->pageView())
       
   698                 m_view->brCtl()->DrawNow();
       
   699         }
       
   700     }
       
   701 }
       
   702 
       
   703 // -----------------------------------------------------------------------------
       
   704 // WebCursor::setPosition
       
   705 // -----------------------------------------------------------------------------
       
   706 void WebCursor::updatePositionAndElemType(const TPoint& pt)
       
   707 {
       
   708     m_pos = pt;
       
   709     m_sprite.SetPosition(pt);
       
   710     WebFrame* frame = getFrameAtPoint(pt);
       
   711     TBrCtlDefs::TBrCtlElementType elType;
       
   712     TRect r;
       
   713     TPoint point(frame->frameView()->viewCoordsInFrameCoords(m_pos));
       
   714     if (m_view && navigableNodeUnderCursor(*frame, point, elType, r)) {
       
   715         m_view->setFocusedElementType(elType);
       
   716     }
       
   717 }
       
   718 
       
   719 // -----------------------------------------------------------------------------
       
   720 // WebCursor::movecursor
       
   721 // -----------------------------------------------------------------------------
       
   722 void WebCursor::moveCursor(int lr,int tb, int scrollRange)
       
   723     {
       
   724     TPoint cp(m_pos);
       
   725     int z = m_view->scalingFactor();
       
   726 
       
   727     //Flipping is set to true only if the user make 3 consective moves in opposite direction
       
   728     //ie if the user went in up down up direction then we apply the flipping logic
       
   729     if ( ( lr*m_previousLr == -1 || tb*m_previousTb == -1) )
       
   730         {
       
   731         m_flipcounter++ ;
       
   732         }
       
   733     else m_flipcounter = 0;
       
   734 
       
   735     m_previousLr = lr;
       
   736     m_previousTb = tb;
       
   737 
       
   738     if (m_view->focusedElementType() == TBrCtlDefs::EElementAnchor && !m_nodeRect.IsEmpty() && m_flipcounter <= 1 ) {
       
   739         TSize nodeSizeInDocCoords(m_view->mainFrame()->frameView()->toDocCoords(m_nodeRect.Size()));
       
   740         if ( tb == 0 && nodeSizeInDocCoords.iWidth < scrollRange) {
       
   741             cp.iX = (lr == -1) ? Min(cp.iX , Max(m_nodeRect.iTl.iX, cp.iX - m_incrLimit.iX)) :
       
   742                                  Max(cp.iX, Min(m_nodeRect.iBr.iX, cp.iX + m_incrLimit.iX));
       
   743         }
       
   744         if ( lr == 0 && nodeSizeInDocCoords.iHeight < scrollRange) {
       
   745             cp.iY = (tb == -1) ? Min(cp.iY, Max(m_nodeRect.iTl.iY, cp.iY - m_incrLimit.iY)) :
       
   746                                  Max(cp.iY, Min(m_nodeRect.iBr.iY, cp.iY + m_incrLimit.iY));
       
   747         }
       
   748     }
       
   749 
       
   750     m_incrLimit.iX -= Abs(m_pos.iX - cp.iX);
       
   751     m_incrLimit.iY -= Abs(m_pos.iY - cp.iY);
       
   752 
       
   753     cp.iX += lr*Min(KCursorIncremental*z/100, m_incrLimit.iX);
       
   754     cp.iY += tb*Min(KCursorIncremental*z/100, m_incrLimit.iY);
       
   755 
       
   756     TRect rec(TPoint(0,0), m_view->offscreenRect().Size());
       
   757     // limit the movement, don't scroll out of the view area
       
   758     cp.iX = Min(rec.Width(), Max( 0 , cp.iX));
       
   759     cp.iY = Min(rec.Height(), Max( 0 , cp.iY));
       
   760 
       
   761     TPoint rPos[] = { cp, cp };
       
   762     rPos[0] -= TPoint(lr*KMiddleStep*z/100,tb*KMiddleStep*z/100);
       
   763 
       
   764     // user is trying hard to focus a small element
       
   765     if ( m_flipcounter > 1 )
       
   766         {
       
   767         int flipDistance = KFlipAdjust * z/(100 * (m_flipcounter - 1));
       
   768         rPos[0] = m_pos + TPoint(lr * flipDistance/2,tb * flipDistance/2);
       
   769         rPos[1] = m_pos + TPoint(lr * flipDistance,tb * flipDistance);
       
   770         }
       
   771 
       
   772     m_pos = rPos[0];
       
   773 
       
   774     for ( int i = 0;i < 2; i++ )
       
   775         {
       
   776         WebFrame* frame = getFrameAtPoint(rPos[i]);
       
   777         if ( !frame ) continue;
       
   778 
       
   779         m_view->page()->focusController()->setFocusedFrame(core(frame));
       
   780         TPoint pt = frame->frameView()->viewCoordsInFrameCoords(rPos[i]);
       
   781 
       
   782         // now let's do the probing
       
   783         TBrCtlDefs::TBrCtlElementType elType = TBrCtlDefs::EElementNone;
       
   784         TRect nr = TRect();
       
   785 
       
   786         bool test = navigableNodeUnderCursor(*frame, pt, elType, nr);
       
   787 
       
   788         TRect rt(frame->frameView()->frameCoordsInViewCoords(nr.iTl),m_view->mainFrame()->frameView()->toViewCoords(nr.Size()));
       
   789         rt.Intersection(rec);
       
   790 
       
   791         if (i == 0 && ( !test || (m_view->focusedElementType() == elType  && rt == m_nodeRect)) ) continue;
       
   792 
       
   793         if ( i == 1 && !test && m_flipCounter <= 1 && !m_nodeRect.IsEmpty())
       
   794             {
       
   795             //Go to webcore to figure out a possible node
       
   796             TRect searchRect = calcSearchRect(lr,tb, scrollRange);
       
   797             TPoint cp(m_pos);
       
   798             WebFrame* f = getFrameAtPoint(cp);
       
   799             if ( !f ) continue;
       
   800 
       
   801             cp = f->frameView()->viewCoordsInFrameCoords(cp);
       
   802             bool found = determineCursorPosition(*f, elType, nr, searchRect, cp, false);
       
   803             if ( found )
       
   804                 {
       
   805                 m_pos = f->frameView()->frameCoordsInViewCoords(cp);
       
   806 
       
   807                 m_nodeRect = TRect(f->frameView()->frameCoordsInViewCoords(nr.iTl),m_view->mainFrame()->frameView()->toViewCoords(nr.Size()) );
       
   808                 m_nodeRect.Intersection(rec);
       
   809                 m_view->setFocusedElementType(elType);
       
   810                 return;
       
   811                 }
       
   812             }
       
   813 
       
   814         m_pos = frame->frameView()->frameCoordsInViewCoords(pt);
       
   815         m_nodeRect = rt;
       
   816         m_view->setFocusedElementType(elType);
       
   817         return;
       
   818         }
       
   819     }
       
   820 
       
   821 
       
   822 bool WebCursor::navigableNodeUnderCursor(WebFrame& webFrame, TPoint& aPoint, TBrCtlDefs::TBrCtlElementType& aElType, TRect& aFocusRect) const
       
   823 {
       
   824     Frame* coreFrame = core(&webFrame);
       
   825     if (!coreFrame->renderer() )
       
   826         return false;
       
   827 
       
   828     Element* node = coreFrame->document()->elementFromPoint(aPoint.iX, aPoint.iY);
       
   829 
       
   830     if (node) {
       
   831         return coreFrame->bridge()->getTypeFromElement(node, aElType, aFocusRect);
       
   832     }
       
   833 
       
   834     return false;
       
   835 }
       
   836 
       
   837 bool WebCursor::determineCursorPosition( WebFrame& webFrame, TBrCtlDefs::TBrCtlElementType& aElType,
       
   838                                          TRect& aFocusRect, TRect& aSearchRect,
       
   839                                          TPoint &aCursorPosition, bool aInitialize)
       
   840 {
       
   841     // FIXME: cursor navigation not implemented
       
   842     IntRect searchRt(aSearchRect);
       
   843     IntPoint pt(aCursorPosition.iX,aCursorPosition.iY);
       
   844     bool found = false;
       
   845 
       
   846     if (aInitialize && core(&webFrame)->document()->focusedNode()) {
       
   847        IntRect nodeRect = core(&webFrame)->document()->focusedNode()->getRect();
       
   848        if (nodeRect.intersects(searchRt)) {
       
   849           IntRect rt = nodeRect;
       
   850           rt.intersect(searchRt);
       
   851           pt = IntPoint( rt.x() + rt.width()>>1, rt.y() + rt.height()>>1 );
       
   852           found = true;
       
   853        }
       
   854     }
       
   855 
       
   856     found = decideCursorPosition(webFrame, searchRt, pt);
       
   857     TPoint newPos(pt.x(),pt.y());
       
   858 
       
   859     bool retest = false;
       
   860     if (found)
       
   861        retest = navigableNodeUnderCursor(webFrame, newPos,aElType,aFocusRect);
       
   862 
       
   863     if (!retest)
       
   864         return false;
       
   865 
       
   866     aCursorPosition = newPos;
       
   867     return retest;
       
   868 }
       
   869 
       
   870 
       
   871 TRect WebCursor::calcSearchRect(int lr, int tb, int scrollRange)
       
   872 {
       
   873     TRect searchRect;
       
   874     TPoint pt(m_nodeRect.iTl);
       
   875     TSize nodeSz(m_view->mainFrame()->frameView()->toDocCoords(m_nodeRect.Size()));
       
   876 
       
   877     WebFrame* focused = getFrameAtPoint(m_pos);
       
   878     if (!focused)
       
   879         return searchRect;
       
   880     pt = focused->frameView()->viewCoordsInFrameCoords(pt);
       
   881 
       
   882     if (focused) {
       
   883         TSize sz( (lr == 0) ? nodeSz.iWidth: scrollRange , (tb == 0) ? nodeSz.iHeight:scrollRange);
       
   884         pt.iX += (tb != 0) ? 0 : (lr == -1) ? -scrollRange: nodeSz.iWidth ;
       
   885         pt.iY += (lr != 0) ? 0 : (tb == -1) ? -scrollRange: nodeSz.iHeight ;
       
   886         searchRect = TRect(pt,sz);
       
   887 
       
   888         TBrCtlDefs::TBrCtlElementType elType = m_view->focusedElementType();
       
   889         if (    elType == TBrCtlDefs::EElementInputBox
       
   890              || elType == TBrCtlDefs::EElementTextAreaBox
       
   891              || elType == TBrCtlDefs::EElementRadioButtonUnSelected
       
   892              || elType == TBrCtlDefs::EElementButton
       
   893              || elType == TBrCtlDefs::EElementCheckBoxUnChecked
       
   894              || elType == TBrCtlDefs::EElementCheckBoxChecked
       
   895              || elType == TBrCtlDefs::EElementRadioButtonSelected )
       
   896           increaseSearchRect(lr, tb, searchRect);
       
   897     }
       
   898     return searchRect;
       
   899 }
       
   900 
       
   901 void WebCursor::increaseSearchRect(int lr,int tb,TRect& aRect)
       
   902 {
       
   903     int width(aRect.Width());
       
   904     int height(aRect.Height());
       
   905 
       
   906     // enlarge the search rect for aggressive probing, the origninal ccb implementation is faulty.
       
   907     if (lr) {
       
   908         if (lr > 0)
       
   909             aRect.SetWidth(width + width*KAggressiveSearch/100);   // right
       
   910         else
       
   911             aRect.iTl.iX -= width*KAggressiveSearch/100;            // left
       
   912     } else if (tb) {
       
   913         if (tb > 0)
       
   914             aRect.SetHeight(height + height*KAggressiveSearch/100); // down
       
   915         else
       
   916             aRect.iTl.iY -= height*KAggressiveSearch/100;           // up
       
   917     }
       
   918     m_flipCounter = 0;
       
   919 }
       
   920 
       
   921 bool WebCursor::decideCursorPosition(WebFrame& webFrame, const IntRect& searchRect, IntPoint& cursorPosition)
       
   922 {
       
   923     int distance = -1;
       
   924     bool found = false;
       
   925     IntPoint cp = cursorPosition;
       
   926 
       
   927     const int minWidth = 5;
       
   928     const int minHeight = 5;
       
   929 
       
   930     Vector<WebCore::IntRect>& recList = *(webFrame.bridge()->focusableRectList());
       
   931 
       
   932     if (recList.isEmpty())
       
   933         return false;
       
   934 
       
   935     for (int i = 0;i < recList.size();i++) {
       
   936         IntRect nr = recList[i];
       
   937 
       
   938         //Resize the rect so that the cursor is comfortably inside the box
       
   939         nr.inflate(-2);
       
   940 
       
   941         if (!nr.intersects(searchRect)) continue;
       
   942 
       
   943         IntRect intersectRect = nr;
       
   944         intersectRect.intersect(searchRect);
       
   945 
       
   946         if ( (nr.width() != intersectRect.width() && intersectRect.width() < minWidth)
       
   947            || (nr.height() != intersectRect.height() && intersectRect.height() < minHeight) )
       
   948             continue;
       
   949 
       
   950         intersectRect.inflate(-1);
       
   951         found = true;
       
   952 
       
   953         IntPoint np = nearestPointInRect(cp,intersectRect);
       
   954         int disFromCursor = (np.x() - cp.x())*(np.x() - cp.x())
       
   955                            + (np.y() - cp.y())*(np.y() - cp.y());
       
   956 
       
   957         if (distance == -1 || distance > disFromCursor) {
       
   958             distance = disFromCursor;
       
   959             cursorPosition = np;
       
   960         }
       
   961     }
       
   962 
       
   963     return found;
       
   964 }
       
   965 
       
   966 WebFrame* WebCursor::getFrameUnderCursor()
       
   967 {
       
   968   return getFrameAtPoint(m_pos);
       
   969 }
       
   970 
       
   971 
       
   972 
       
   973 // END OF FILE