void ViewNavigationDelegate::MoveMouseCursorToNode(WebCore::Node* node, bool scrollIfNecessary)
{
	if (node)
	{
		WebCore::HTMLElement* element = (WebCore::HTMLElement*)node;

		WebCore::IntRect rect = element->getRect();
		WebCore::IntPoint frameOffset;
		WebCore::IntPoint scrollOffset;

		WebCore::FrameView* pFrameView = element->document()->view(); //Can be NULL
		if(pFrameView)
		{
			//Use move here instead of setX/setY as it results in 1 call instead of two and takes advantage that ctor sets x,y to 0.
			frameOffset.move(pFrameView->x(), pFrameView->y());
			scrollOffset.move(pFrameView->scrollOffset().width(), pFrameView->scrollOffset().height());
		}

		int width = mView->GetSize().mWidth;
		int height = mView->GetSize().mHeight;

		// This will be true if this function is called from anywhere except JumpToNearestElement(). This enables us to not lose the cursor during
		// arbitrary jumping of elements from either code or webpage using the Navigation APIs.
		if(scrollIfNecessary)
		{
			int cursorX, cursorY;
			mView->GetCursorPosition(cursorX, cursorY);

			WebCore::IntPoint targetCursorLocation(frameOffset.x()+rect.x()+rect.width()/2  - scrollOffset.x(), frameOffset.y()+rect.y()+rect.height()/2  - scrollOffset.y());
			// Added 1 in all the line delta below resulting in a better visual behavior when the element happens to be at the edge.
			if(targetCursorLocation.y() > height)
			{
                float numLinesDelta = (((targetCursorLocation.y() - cursorY)/WebCore::Scrollbar::pixelsPerLineStep())+1);
				ScrollOnJump(true, -120, numLinesDelta);
			}
			if(targetCursorLocation.y()< 0.0f)
			{
				float numLinesDelta = (((cursorY - targetCursorLocation.y())/WebCore::Scrollbar::pixelsPerLineStep())+1);
				ScrollOnJump(true, 120, numLinesDelta);
			}
			if(targetCursorLocation.x() > width)
			{
				float numLinesDelta = (((targetCursorLocation.x() - cursorX)/WebCore::Scrollbar::pixelsPerLineStep())+1);
				ScrollOnJump(false, -120, numLinesDelta);
			}
			if(targetCursorLocation.x()< 0.0f)
			{
				float numLinesDelta = (((cursorX - targetCursorLocation.x())/WebCore::Scrollbar::pixelsPerLineStep())+1);
				ScrollOnJump(false, 120, numLinesDelta);
			}

			// Read the scroll offset again as it may have changed.
			if(pFrameView) 
			{
				scrollOffset.setX(pFrameView->scrollOffset().width());
				scrollOffset.setY(pFrameView->scrollOffset().height());
			}
		}

		mBestNodeFrame	= element->document()->frame(); //Can be NULL
		mBestNodeX		= frameOffset.x()  + rect.x();
		mBestNodeY		= frameOffset.y()  + rect.y();
		mBestNodeWidth	= rect.width();
		mBestNodeHeight = rect.height();

		int lastX, lastY;
		mView->GetCursorPosition(lastX, lastY);
		int newX		= mBestNodeX + rect.width()/2  - scrollOffset.x();
		int newY		= mBestNodeY + rect.height()/2 - scrollOffset.y();

		EA::WebKit::MouseMoveEvent moveEvent;
		memset( &moveEvent, 0, sizeof(moveEvent) );
		const int cursorInset = 5;// Make cursor stay inside 5 pixels from boundaries. No known issues but added this as a safety measure so that we do not lose cursor ever.
		moveEvent.mX	= Clamp( cursorInset, newX, width - cursorInset );
		moveEvent.mY	= Clamp( cursorInset, newY, height - cursorInset );

		mView->OnMouseMoveEvent( moveEvent );

		if(EAWebKitClient* const pClient = GetEAWebKitClient())
		{
			CursorMovedInfo cmInfo(mView, mView->GetUserData(), moveEvent.mX, moveEvent.mY);
			pClient->CursorMoved(cmInfo);
		}

		UpdateCachedHints(node);

	}
}
Beispiel #2
0
void ChromeClient::invalidateContentsAndWindow(const WebCore::IntRect& rect, bool immediate)
{
    m_webView->addDirtyArea(rect.x(), rect.y(), rect.width(), rect.height());
    //dbgMsg(L"invalidateContentsAndWindow\n");
}
Beispiel #3
0
void PageClientImpl::setViewNeedsDisplay(const WebCore::IntRect& rect)
{
    gtk_widget_queue_draw_area(m_viewWidget, rect.x(), rect.y(), rect.width(), rect.height());
}
		void DocumentNavigator::FindBestNode(WebCore::Node* rootNode)
		{
			// Note by Arpit Baldeva - Changed the recursive algorithm to an iterative algorithm. This results in 25% to 40% increase in efficiency.
			
			while (rootNode) 
			{
				IsNodeNavigableDelegate nodeNavigableDelegate(mView);
				// As it turns out, getRect on HTMLElement is pretty expensive. So we don't do it inside the delegate as we require getRect here too. We do that check here.
				// It is at least ~15% more efficient and can be up to ~25% more efficient (depends on the page layout and current node you are at).
				nodeNavigableDelegate(rootNode,false);

				if (nodeNavigableDelegate.FoundNode())
				{
					WebCore::HTMLElement* htmlElement = (WebCore::HTMLElement*) rootNode;
					WebCore::IntRect rectAbsolute = htmlElement->getRect();		
					// Adjust the rectangle position based on the frame offset so that we have absolute geometrical position.
					WebCore::FrameView* pFrameView = htmlElement->document()->view(); //Can be NULL
					if(pFrameView)
					{
						rectAbsolute.setX(rectAbsolute.x() + pFrameView->x());
						rectAbsolute.setY(rectAbsolute.y() + pFrameView->y());
					}

					 /* printf("Looking at ELEMENT_NODE : nodeName=%S (%d,%d)->(%d,%d) ThetaRange(%f,%f)\n\n%S\n-----------------------------------\n", 
											htmlElement->tagName().charactersWithNullTermination(),
											rect.topLeft().x(),rect.topLeft().y(),
											rect.bottomRight().x(), rect.bottomRight().y(),
											mMinThetaRange,mMaxThetaRange,
											htmlElement->innerHTML().charactersWithNullTermination()
											);
										*/

					if (!WouldBeTrappedInElement(rectAbsolute,mStartingPosition,mDirection))
					{
						if (!TryingToDoPerpendicularJump(rectAbsolute,mPreviousNodeRect,mDirection))
						{
							if(rectAbsolute.width()>=1 && rectAbsolute.height() >= 1) //Avoid 0 size elements
							{
								if (doAxisCheck(rectAbsolute))
								{
									PolarRegion pr(rectAbsolute, mStartingPosition);

									if (pr.minR < mMinR )
									{
										if (areAnglesInRange(pr.minTheta,pr.maxTheta))
										{
											mMinR = pr.minR;

											EAW_ASSERT( *(uint32_t*)rootNode > 10000000u );

											//mBestNode = rootNode; //We don't assign it here since we do the Z-layer testing later on.
											FoundNodeInfo foundNodeInfo = {rootNode, mMinR};
											mNodeListContainer->mFoundNodes.push_back(foundNodeInfo);
											/*printf("Found ELEMENT_NODE : nodeName=%s (%d,%d)->(%d,%d) polar: R(%f,%f) Theta(%f,%f) ThetaRange(%f,%f)  \n", 
											(char*)htmlElement->nodeName().characters(),
											rect.topLeft().x(),rect.topLeft().y(),
											rect.bottomRight().x(), rect.bottomRight().y(),
											pr.minR,pr.maxR,pr.minTheta,pr.maxTheta,
											mMinThetaRange,mMaxThetaRange
											);*/
											
										} 
										else
										{
											
#if EAWEBKIT_ENABLE_JUMP_NAVIGATION_DEBUGGING
											mNodeListContainer->mRejectedByAngleNodes.push_back(rootNode);
#endif
											/*printf("RejectedA ELEMENT_NODE : nodeName=%s (%d,%d)->(%d,%d) polar: R(%f,%f) Theta(%f,%f) ThetaRange(%f,%f)  \n", 
											(char*)htmlElement->nodeName().characters(),
											rect.topLeft().x(),rect.topLeft().y(),
											rect.bottomRight().x(), rect.bottomRight().y(),
											pr.minR,pr.maxR,pr.minTheta,pr.maxTheta,
											mMinThetaRange,mMaxThetaRange
											);*/
										}
									} 
									else
									{
#if EAWEBKIT_ENABLE_JUMP_NAVIGATION_DEBUGGING
										mNodeListContainer->mRejectedByRadiusNodes.push_back(rootNode);
#endif
										/*printf("RejectedR ELEMENT_NODE : nodeName=%s (%d,%d)->(%d,%d) polar: R(%f,%f) Theta(%f,%f) ThetaRange(%f,%f)  \n", 
										(char*)htmlElement->nodeName().characters(),
										rect.topLeft().x(),rect.topLeft().y(),
										rect.bottomRight().x(), rect.bottomRight().y(),
										pr.minR,pr.maxR,pr.minTheta,pr.maxTheta,
										mMinThetaRange,mMaxThetaRange
										);*/
									}
								}
								else
								{
									//printf(" - failed axis check\n");
								}
							}
							else
							{
								//printf(" - too small\n");
							}
						}
						else 
						{
							//printf(" - perpendicular\n");
						}							
					}
					else
					{
#if EAWEBKIT_ENABLE_JUMP_NAVIGATION_DEBUGGING
						mNodeListContainer->mRejectedWouldBeTrappedNodes.push_back(rootNode);
#endif
					}
				}
				
				rootNode = rootNode->traverseNextNode();
			}

			// Make sure that this element can be jumped to by passing z-check. This makes sure that we jump only on the element
			// at the top most layer (For example, a CSS+JavaScript pop up).
			// We don't try and check against Z-layer in the loop above as it has significant performance penalty. On an average, it causes traversal to be 50% slower. So what we do 
			// instead is to collect all the nodes and at the end, traverse this list from the end to begining. It is important to traverse from end as that is where the most suited element is 
			// based on the position.

			WebCore::Node* bestNode = NULL;
			float radialDistance = FLT_MAX; // A high value so that the max distance between any two elements in the surface is under it.
			bool matched = false;
			for (WebCoreFoundNodeInfoListReverseIterator rIt = mNodeListContainer->mFoundNodes.rbegin(); rIt != mNodeListContainer->mFoundNodes.rend(); ++rIt)
			{
				bestNode = (*rIt).mFoundNode;
				radialDistance = (*rIt).mRadialDistance;
				WebCore::HTMLElement* element = (WebCore::HTMLElement*)bestNode;

				WebCore::Frame*		frame = element->document()->frame();
				WebCore::FrameView* pFrameView = element->document()->view(); 

				WebCore::IntRect rect = element->getRect(); //This list is decently small so we don't worry about caching the rect size.
				// ElementFromPoint expects the point in its own coordinate system so we don't need to adjust the rectangle to its absolute position
				// on screen
				// elementFromPoint API changed compared to 1.x. The simplest thing to do at the moment is to adjust our input.
				int inputX = (rect.x()+rect.width()/2 - pFrameView->scrollX())/frame->pageZoomFactor();
				int inputY = (rect.y()+rect.height()/2 - pFrameView->scrollY())/frame->pageZoomFactor();
				
				WebCore::Node* hitElement = mDocument->elementFromPoint(inputX,inputY);
				while (hitElement)
				{
					if(bestNode == hitElement)
					{
						matched = true;
						break;
					}
					hitElement = hitElement->parentNode();//We need to find the element that responds to the events as that is what we jump to. For example, we don't jump to a "span".
				};

				if(matched)
					break;
			}

			if(matched)
			{
				mBestNode = bestNode;
				mMinR = radialDistance;
			}
			else
			{
				mBestNode = 0; //We didn't match anything based on the Z-layer testing.
				mMinR = FLT_MAX;
			}


			// A way to do Post Order traversal.
			//while (WebCore::Node* firstChild = rootNode->firstChild())
			//	rootNode = firstChild;
			//while(rootNode)
			//{
			//	rootNode = rootNode->traverseNextNodePostOrder();
			//}


/*
			//////////////////////////////////////////////////////////////////////////
			// THEN, FIND THE CHILDREN
			if (rootNode && rootNode->childNodeCount() > 0)
			{
				PassRefPtr<WebCore::NodeList> children = rootNode->childNodes();

				const uint32_t length = children->length();

				for (uint32_t i=0; i < length; ++i)
				{
					WebCore::Node* child = children->item(i);
					if (child)
					{
						FindBestNode(child);
					}
				}
			}
*/		
		}
Beispiel #5
0
void CachedNode::fixUpCursorRects(const CachedFrame* frame)
{
    if (mFixedUpCursorRects)
        return;
    mFixedUpCursorRects = true;
    // if the hit-test rect doesn't intersect any other rect, use it
    if (mHitBounds != mBounds && mHitBounds.contains(mBounds) &&
            frame->checkRings(this, mCursorRing, mHitBounds)) {
        DBG_NAV_LOGD("use mHitBounds (%d,%d,%d,%d)", mHitBounds.x(),
            mHitBounds.y(), mHitBounds.width(), mHitBounds.height());
        mUseHitBounds = true;
        return;
    }
    if (mNavableRects <= 1)
        return;
    // if there is more than 1 rect, and the bounds doesn't intersect
    // any other cursor ring bounds, use it
    if (frame->checkRings(this, mCursorRing, mBounds)) {
        DBG_NAV_LOGD("use mBounds (%d,%d,%d,%d)", mBounds.x(),
            mBounds.y(), mBounds.width(), mBounds.height());
        mUseBounds = true;
        return;
    }
#if DEBUG_NAV_UI
    {
        WebCore::IntRect* boundsPtr = mCursorRing.begin() - 1;
        const WebCore::IntRect* const boundsEnd = mCursorRing.begin() + mCursorRing.size();
        while (++boundsPtr < boundsEnd)
            LOGD("%s %d:(%d, %d, %d, %d)\n", __FUNCTION__, boundsPtr - mCursorRing.begin(),
                boundsPtr->x(), boundsPtr->y(), boundsPtr->width(), boundsPtr->height());
    }
#endif
    // q: need to know when rects are for drawing and hit-testing, but not mouse down calcs?
    bool again;
    do {
        again = false;
        size_t size = mCursorRing.size();
        WebCore::IntRect* unitBoundsPtr = mCursorRing.begin() - 1;
        const WebCore::IntRect* const unitBoundsEnd = mCursorRing.begin() + size;
        while (++unitBoundsPtr < unitBoundsEnd) {
            // any other unitBounds to the left or right of this one?
            int unitTop = unitBoundsPtr->y();
            int unitBottom = unitBoundsPtr->bottom();
            int unitLeft = unitBoundsPtr->x();
            int unitRight = unitBoundsPtr->right();
            WebCore::IntRect* testBoundsPtr = mCursorRing.begin() - 1;
            while (++testBoundsPtr < unitBoundsEnd) {
                if (unitBoundsPtr == testBoundsPtr)
                    continue;
                int testTop = testBoundsPtr->y();
                int testBottom = testBoundsPtr->bottom();
                int testLeft = testBoundsPtr->x();
                int testRight = testBoundsPtr->right();
                int candidateTop = unitTop > testTop ? unitTop : testTop;
                int candidateBottom = unitBottom < testBottom ? unitBottom : testBottom;
                int candidateLeft = unitRight < testLeft ? unitRight : testRight;
                int candidateRight = unitRight > testLeft ? unitLeft : testLeft;
                bool leftRight = true;
                if (candidateTop + OVERLAP >= candidateBottom ||
                        candidateLeft + OVERLAP >= candidateRight) {
                    candidateTop = unitBottom < testTop ? unitBottom : testBottom;
                    candidateBottom = unitBottom > testTop ? unitTop : testTop;
                    candidateLeft = unitLeft > testLeft ? unitLeft : testLeft;
                    candidateRight = unitRight < testRight ? unitRight : testRight;
                    if (candidateTop + OVERLAP >= candidateBottom ||
                            candidateLeft + OVERLAP >= candidateRight)
                        continue;
                    leftRight = false;
                }
                // construct candidate to add
                WebCore::IntRect candidate = WebCore::IntRect(candidateLeft, candidateTop, 
                    candidateRight - candidateLeft, candidateBottom - candidateTop);
                // does a different unit bounds intersect the candidate? if so, don't add
                WebCore::IntRect* checkBoundsPtr = mCursorRing.begin() - 1;
                while (++checkBoundsPtr < unitBoundsEnd) {
                    if (checkBoundsPtr->intersects(candidate) == false)
                        continue;
                    if (leftRight) {
                        if (candidateTop >= checkBoundsPtr->y() &&
                                candidateBottom > checkBoundsPtr->bottom())
                            candidateTop = checkBoundsPtr->bottom(); 
                        else if (candidateTop < checkBoundsPtr->y() &&
                                candidateBottom <= checkBoundsPtr->bottom())
                            candidateBottom = checkBoundsPtr->y();
                        else
                            goto nextCheck;
                    } else {
                        if (candidateLeft >= checkBoundsPtr->x() &&
                                candidateRight > checkBoundsPtr->right())
                            candidateLeft = checkBoundsPtr->right(); 
                        else if (candidateLeft < checkBoundsPtr->x() &&
                                candidateRight <= checkBoundsPtr->right())
                            candidateRight = checkBoundsPtr->x();
                        else
                            goto nextCheck;
                    }
                 } 
                 candidate = WebCore::IntRect(candidateLeft, candidateTop, 
                    candidateRight - candidateLeft, candidateBottom - candidateTop);
                 ASSERT(candidate.isEmpty() == false);
#if DEBUG_NAV_UI
                LOGD("%s %d:(%d, %d, %d, %d)\n", __FUNCTION__, mCursorRing.size(),
                    candidate.x(), candidate.y(), candidate.width(), candidate.height());
#endif
                mCursorRing.append(candidate);
                again = true;
                goto tryAgain;
        nextCheck:
                continue;
            }
        }
tryAgain:
        ;
    } while (again);
}
void WebViewPrivate::scrollBackingStore(WebCore::FrameView* view, int dx, int dy, const WebCore::IntRect& scrollViewRect, const WebCore::IntRect& clipRect)
{
    IntRect updateRect = clipRect;
    updateRect.intersect(scrollViewRect);
    
#if 0
    dy = -dy;
    dx = -dx;
    
    int svWidth = scrollViewRect.width();
    int svHeight = scrollViewRect.height();
    int dirtyX = 0, dirtyY = 0, dirtyW = 0, dirtyH = 0;

    if (dy == 0 && dx < 0 && -dx < svWidth) {
        dirtyW = -dx;
        dirtyH = svHeight;
    }
    else if (dy == 0 && dx > 0 && dx < svWidth) {
        dirtyX = svWidth - dx;
        dirtyW = dx;
        dirtyH = svHeight;
    }
    else if (dx == 0 && dy < 0 && -dy < svHeight) {
        dirtyW = svWidth;
        dirtyH = -dy;
    }
    else if (dx == 0 && dy > 0 && dy < svHeight) {
        dirtyY = svHeight - dy;
        dirtyW = svWidth;
        dirtyH = dy;
    }

    if (m_webView->viewWindow() && dirtyW) {
        m_srcRect.x = dx > 0 ? dx + scrollViewRect.x() : scrollViewRect.x();
        m_srcRect.y = dy > 0 ? dy + scrollViewRect.y() : scrollViewRect.y();
        m_srcRect.w = dx > 0 ? scrollViewRect.width() - dx : scrollViewRect.width() + dx;
        m_srcRect.h = dy > 0 ? scrollViewRect.height() - dy : scrollViewRect.height() + dy;

        m_dstRect.x = dx > 0 ? scrollViewRect.x() : -dx + scrollViewRect.x();
        m_dstRect.y = dy > 0 ? scrollViewRect.y() : -dy + scrollViewRect.y();
        m_dstRect.w = dx > 0 ? scrollViewRect.width() - dx : scrollViewRect.width() + dx;
        m_dstRect.h = dy > 0 ? scrollViewRect.height() -dy : scrollViewRect.height() + dy;

        int x, y, w, h = 0;
        if (dx > 0) {
            m_srcRect.x += m_scrollUpdateRect.width();
            m_srcRect.w -= m_scrollUpdateRect.width();
            x = scrollViewRect.x() + dirtyX - m_scrollUpdateRect.width();
            w = dirtyW + m_scrollUpdateRect.width();
        } else if (dx < 0) {
            m_dstRect.x += m_scrollUpdateRect.width();
            m_srcRect.w -= m_scrollUpdateRect.width();
            x = scrollViewRect.x() + dirtyX + m_scrollUpdateRect.width();
            w = dirtyW + m_scrollUpdateRect.width();
        } else {
            x = scrollViewRect.x() + dirtyX;
            w = dirtyW;
        }

        if (dy > 0) {
            m_srcRect.y += m_scrollUpdateRect.height();
            m_srcRect.h -= m_scrollUpdateRect.height();
            y = scrollViewRect.y() + dirtyY - m_scrollUpdateRect.height();
            h = dirtyH + m_scrollUpdateRect.height();
        } else if (dy < 0) {
            m_dstRect.y += m_scrollUpdateRect.height();
            m_srcRect.h -= m_scrollUpdateRect.height();
            y = scrollViewRect.y() + dirtyY + m_scrollUpdateRect.height();
            h = dirtyH + m_scrollUpdateRect.height();
        } else {
            y = scrollViewRect.y() + dirtyY;
            h = dirtyH;
        }

        Uint32 rmask, gmask, bmask, amask;
#if !PLATFORM(AMIGAOS4) && SDL_BYTEORDER == SDL_BIG_ENDIAN
        rmask = 0xff000000;
        gmask = 0x00ff0000;
        bmask = 0x0000ff00;
        amask = 0x000000ff;
#else
        rmask = 0x00ff0000;
        gmask = 0x0000ff00;
        bmask = 0x000000ff;
        amask = 0xff000000;
#endif

        if (m_scrollSurface)
            SDL_FreeSurface(m_scrollSurface);
        m_scrollSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, m_dstRect.w, m_dstRect.h , 32, rmask, gmask, bmask, amask);

        SDL_Rect dRect = {0, 0, m_dstRect.w, m_dstRect.h};
        SDL_BlitSurface(m_webView->viewWindow(), &m_srcRect, m_scrollSurface, &dRect);

        m_scrollUpdateRect = IntRect(x, y, w, h);
        m_scrollUpdateRect.intersect(scrollViewRect);

        Scrollbar* hBar = view->horizontalScrollbar();
        Scrollbar* vBar = view->verticalScrollbar();
        if (dx && hBar)
            m_hUpdateRect = IntRect(scrollViewRect.x() + hBar->x(), scrollViewRect.y() + hBar->y(), hBar->width(), hBar->height());
        if (dy && vBar)
            m_vUpdateRect = IntRect(scrollViewRect.x() + vBar->x(), scrollViewRect.y() + vBar->y(), vBar->width(), vBar->height());

        m_webView->addToDirtyRegion(m_scrollUpdateRect);
        sendExposeEvent(m_scrollUpdateRect);
    }
#else
    m_webView->addToDirtyRegion(updateRect);
    sendExposeEvent(updateRect);
#endif
}
Beispiel #7
0
void PageClientImpl::setViewNeedsDisplay(const WebCore::IntRect& rect)
{
    evas_object_image_data_update_add(m_viewObject, rect.x(), rect.y(), rect.width(), rect.height());
}