WebCore::IntRect SelectionHandler::selectionEndCaretRect()
{
    if (!m_selectionActive)
        return IntRect();

    ASSERT(m_webPage && m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection());

    WebCore::IntRect caretLocation(m_webPage->focusedOrMainFrame()->selection()->selection().visibleEnd().absoluteCaretBounds());

    SelectionController nextCaretSelection;
    nextCaretSelection.setSelection(VisibleSelection(m_webPage->focusedOrMainFrame()->selection()->selection().visibleEnd()));
    nextCaretSelection.modify(SelectionController::AlterationMove, SelectionController::DirectionForward, CharacterGranularity);
    WebCore::IntRect nextCaretLocation(nextCaretSelection.selection().visibleStart().absoluteCaretBounds());

    if (nextCaretLocation.y() == caretLocation.y()) {
        // The next caret position is on this line, use the middle of the character
        // as the active selection point.
        caretLocation.move((nextCaretLocation.x() - caretLocation.x()) / 2, 0);
    } else {
        // Caret position is at the end of a line, advance 1 pixel to ensure
        // overlap with character.
        caretLocation.move(1, 0);
    }

    if (m_webPage->focusedOrMainFrame()->ownerRenderer()) {
        WebCore::IntPoint frameOffset = m_webPage->focusedOrMainFrame()->ownerRenderer()->absoluteContentBox().location();
        caretLocation.move(frameOffset.x(), frameOffset.y());
    }
    return caretLocation;
}
示例#2
0
WebCore::IntPoint ChromeClient::screenToWindow(const WebCore::IntPoint& screePoint) const 
{
    HWND hwnd = m_webView ? m_webView->hostWindow() : NULL;
    if (!IsWindow(hwnd))
        return screePoint;

    POINT tempPoint = { screePoint.x(), screePoint.y() };
    ScreenToClient(hwnd, &tempPoint);

    WebCore::IntPoint windowPoint(tempPoint.x, tempPoint.y);
    return windowPoint;
}
示例#3
0
static inline void setCommonMouseEventFields(XEventType& xEvent, const WebEventType& webEvent, const WebCore::IntPoint& pluginLocation)
{
    xEvent.root = rootWindowID();
    xEvent.subwindow = 0;
    xEvent.time = xTimeStamp(webEvent.timestamp());
    xEvent.x = webEvent.position().x() - pluginLocation.x();
    xEvent.y = webEvent.position().y() - pluginLocation.y();
    xEvent.x_root = webEvent.globalPosition().x();
    xEvent.y_root = webEvent.globalPosition().y();
    xEvent.state = xKeyModifiers(webEvent);
    xEvent.same_screen = true;
}
示例#4
0
WebKitHitTestResult* kit(const WebCore::HitTestResult& result)
{
    guint context = WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT;
    GOwnPtr<char> linkURI(0);
    GOwnPtr<char> imageURI(0);
    GOwnPtr<char> mediaURI(0);
    WebKitDOMNode* node = 0;
    WebCore::Frame* targetFrame;
    WebCore::IntPoint point;

    if (!result.absoluteLinkURL().isEmpty()) {
        context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK;
        linkURI.set(g_strdup(result.absoluteLinkURL().string().utf8().data()));
    }

    if (!result.absoluteImageURL().isEmpty()) {
        context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE;
        imageURI.set(g_strdup(result.absoluteImageURL().string().utf8().data()));
    }

    if (!result.absoluteMediaURL().isEmpty()) {
        context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA;
        mediaURI.set(g_strdup(result.absoluteMediaURL().string().utf8().data()));
    }

    if (result.isSelected())
        context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION;

    if (result.isContentEditable())
        context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE;

    if (result.innerNonSharedNode())
        node = kit(result.innerNonSharedNode());

    targetFrame = result.targetFrame();
    if (targetFrame && targetFrame->view()) {
        // Convert document coords to widget coords.
        point = targetFrame->view()->contentsToWindow(result.point());
    } else
        point = result.point();

    return WEBKIT_HIT_TEST_RESULT(g_object_new(WEBKIT_TYPE_HIT_TEST_RESULT,
                                               "link-uri", linkURI.get(),
                                               "image-uri", imageURI.get(),
                                               "media-uri", mediaURI.get(),
                                               "context", context,
                                               "inner-node", node,
                                               "x", point.x(),
                                               "y", point.y(),
                                               NULL));
}
WebCore::IntRect SelectionHandler::selectionStartCaretRect()
{
    if (!m_selectionActive)
        return IntRect();

    ASSERT(m_webPage && m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection());

    WebCore::IntRect caretLocation(m_webPage->focusedOrMainFrame()->selection()->selection().visibleStart().absoluteCaretBounds());

    if (m_webPage->focusedOrMainFrame()->ownerRenderer()) {
        WebCore::IntPoint frameOffset = m_webPage->focusedOrMainFrame()->ownerRenderer()->absoluteContentBox().location();
        caretLocation.move(frameOffset.x(), frameOffset.y());
    }
    return caretLocation;
}
void SelectionHandler::selectObject(WebCore::IntPoint& location, TextGranularity granularity)
{
    m_selectionActive = true;

    ASSERT(m_webPage && m_webPage->mainFrame() && m_webPage->mainFrame()->selection());
    Frame* frame = m_webPage->mainFrame();

#if SHOWDEBUG_SELECTIONHANDLER
    Olympia::Platform::log(Olympia::Platform::LogLevelInfo, "SelectionHandler::selectWord adjusted points %d, %d", location.x(), location.y());
#endif

    expandSelectionToGranularity(frame, location.x(), location.y(), granularity, m_webPage->m_inputHandler->isInputMode());

    // Need to manually trigger notification as response to change.
    selectionPositionChanged();
}
示例#7
0
void EwkView::showContextMenu(WebContextMenuProxyEfl* contextMenuProxy, const WebCore::IntPoint& position, const Vector<WebContextMenuItemData>& items)
{
    Ewk_View_Smart_Data* sd = smartData();
    ASSERT(sd->api);

    ASSERT(contextMenuProxy);

    if (!sd->api->context_menu_show)
        return;

    if (m_contextMenu)
        hideContextMenu();

    m_contextMenu = Ewk_Context_Menu::create(this, contextMenuProxy, items);

    sd->api->context_menu_show(sd, position.x(), position.y(), m_contextMenu.get());
}
示例#8
0
void SelectionOverlay::paintContents(const GraphicsLayer* layer, GraphicsContext& c, GraphicsLayerPaintingPhase, const IntRect& inClip)
{
    if (!layer->platformLayer()->superlayer())
        return;

    Selection::iterator it = m_selection.find(layer->platformLayer()->superlayer()->owner());
    if (it == m_selection.end())
        return;

    const Vector<WebCore::FloatQuad>& quads = it->value;
    GraphicsLayer* parent = it->key;

    IntRect clip(inClip);
    clip.move(parent->offsetFromRenderer().width(), parent->offsetFromRenderer().height());

    c.save();

    c.translate(-parent->offsetFromRenderer().width(), -parent->offsetFromRenderer().height());

    Color color = RenderTheme::defaultTheme()->activeSelectionBackgroundColor();
    c.setFillColor(color, ColorSpaceDeviceRGB);

    for (unsigned i = 0; i < quads.size(); ++i) {
        FloatRect rectToPaint = quads[i].boundingBox();

        // Selection on non-composited sub-frames need to be adjusted.
        if (!m_page->focusedOrMainFrame()->contentRenderer()->isComposited()) {
            WebCore::IntPoint framePosition = m_page->frameOffset(m_page->focusedOrMainFrame());
            rectToPaint.move(framePosition.x(), framePosition.y());
        }

        rectToPaint.intersect(clip);
        if (rectToPaint.isEmpty())
            continue;

        c.fillRect(rectToPaint);
    }

    c.restore();
}
示例#9
0
WKPoint WKViewContentsToUserViewport(WKViewRef viewRef, WKPoint point)
{
    WebCore::IntPoint result = toImpl(viewRef)->contentsToUserViewport(toIntPoint(point));
    return WKPointMake(result.x(), result.y());
}
示例#10
0
WKPoint WKViewUserViewportToScene(WKViewRef viewRef, WKPoint point)
{
    WebCore::IntPoint result = toImpl(viewRef)->userViewportToScene(toIntPoint(point));
    return WKPointMake(result.x(), result.y());
}
bool ViewNavigationDelegate::JumpToNearestElement(EA::WebKit::JumpDirection direction, bool scrollIfElementNotFound)
{

	// Note by Arpit Baldeva:
	// We have a problem here. mpModalInputClient object is supposed to be used for Modal input only however the only class using this object 
	// is html SELECT element(implemented as a popup). But in reality, html SELECT element is NOT modal. So it is little ill-conceived. 
	// For example, in all the browsers, if you scroll the mouse wheel on the frame, the SELECT element disappears and the actual frame scrolls.

	// For any modal input needs on a web page, the users are advised to use the Z-layer technique with Javascript/CSS - http://jqueryui.com/demos/dialog/#modal-confirmation.

	// The problem we want to solve here is have the SELECT element respond to the controller input correctly(select element one by one).
	// But the button event information is lost by the time we are in the EA::WebKit::View. For the foreseeable future, there is no candidate
	// other than html SELECT element which is implemented as a modal popup inside EAWebKit. So inside EA::WebKit::View, we create a dummy
	// button event from the Jump direction and make SELECT respond to it. If any other object starts using the modal input, this would need to be
	// revisited. But then, we'll need to solve a plethora of issues. So we do minimum work here to not break other things.

	IOverlayInputClient* pOverlayInputClient = mView->GetOverlayInputClient();

	bool handledByOverlayInputClient = false;
	if(pOverlayInputClient)
	{
		EA::WebKit::ButtonEvent btnEvent;
		switch(direction)
		{
			/*
			case EA::WebKit::JumpLeft:
			{
			btnEvent.mID = EA::WebKit::kButton0;
			handledByOverlayInputClient = pOverlayInputClient->OnButtonEvent(btnEvent);
			}
			*/
		case EA::WebKit::JumpUp:
			{
				btnEvent.mID = EA::WebKit::kButton1;
				handledByOverlayInputClient =  pOverlayInputClient->OnButtonEvent(btnEvent);
				break;
			}
			/*
			case EA::WebKit::JumpRight:
			{
			btnEvent.mID = EA::WebKit::kButton2;
			handledByOverlayInputClient =  pOverlayInputClient->OnButtonEvent(btnEvent);
			}
			*/
		case EA::WebKit::JumpDown:
			{
				btnEvent.mID = EA::WebKit::kButton3;
				handledByOverlayInputClient =  pOverlayInputClient->OnButtonEvent(btnEvent);
				break;
			}
		default:
			// We don't return and allow any other button press to go to the main View. At the same time, we make the SELECT element lose focus.
			{
				pOverlayInputClient->OnFocusChangeEvent(false);
				break;
			}
		}
	}

	if(handledByOverlayInputClient)
		return true;

	int lastX, lastY;
	mView->GetCursorPosition(lastX, lastY);

	// Following is a shortcut to drive navigation from a page.
	switch (direction)
	{
	case EA::WebKit::JumpRight:
		if (GetFixedString(mCachedNavigationRightId)->compare(""))
		{
			if (!GetFixedString(mCachedNavigationRightId)->compare("ignore"))
			{
				return false;
			}

			if (JumpToId(GetFixedString(mCachedNavigationRightId)->c_str()))
			{
				return true;
			}
		}
		break;

	case EA::WebKit::JumpDown:
		if (GetFixedString(mCachedNavigationDownId)->compare(""))
		{
			if (!GetFixedString(mCachedNavigationDownId)->compare("ignore"))
			{
				return false;
			}

			if (JumpToId(GetFixedString(mCachedNavigationDownId)->c_str()))
			{
				return true;
			}
		}
		break;

	case EA::WebKit::JumpLeft:
		if (GetFixedString(mCachedNavigationLeftId)->compare(""))
		{
			if (!GetFixedString(mCachedNavigationLeftId)->compare("ignore"))
			{
				return false;
			}

			if (JumpToId(GetFixedString(mCachedNavigationLeftId)->c_str()))
			{
				return true;
			}
		}
		break;

	case EA::WebKit::JumpUp:
		if (GetFixedString(mCachedNavigationUpId)->compare(""))
		{
			if (!GetFixedString(mCachedNavigationUpId)->compare("ignore"))
			{
				return false;
			}

			if (JumpToId(GetFixedString(mCachedNavigationUpId)->c_str()))
			{
				return true;
			}
		}
		break;

	default:
		EAW_FAIL_MSG("Should not have got here\n");
	}


	// Iterate over all the frames and find the closest element in any of all the frames.
	WebCore::Frame* pFrame		= mView->GetFrame();
	float currentRadialDistance = FLT_MAX; // A high value to start with so that the max distance between any two elements in the surface is under it.
	WebCore::Node* currentBestNode = NULL;
	while(pFrame)
	{
		WebCore::Document* document = pFrame->document();
		EAW_ASSERT(document);

		if(document)
		{
			WebCore::FrameView* pFrameView = document->view();
			WebCore::IntPoint scrollOffset;
			if(pFrameView)
			{
 				scrollOffset.setX(pFrameView->scrollOffset().width());
 				scrollOffset.setY(pFrameView->scrollOffset().height());
			}

			// We figure out the start position(It is center of the currently hovered element almost all the time but can be slightly different 
			// due to scroll sometimes).
			mCentreX = lastX + scrollOffset.x();
			mCentreY = lastY + scrollOffset.y();

			DocumentNavigator navigator(mView, document, direction, WebCore::IntPoint(mCentreX, mCentreY), mBestNodeX, mBestNodeY, mBestNodeWidth, mBestNodeHeight, mJumpNavigationParams.mNavigationTheta, mJumpNavigationParams.mStrictAxesCheck, currentRadialDistance);
			navigator.FindBestNode(document);

			if(navigator.GetBestNode())
			{
				currentBestNode			= navigator.GetBestNode();
				currentRadialDistance	= navigator.GetBestNodeRadialDistance();
			}

		}

		pFrame = pFrame->tree()->traverseNext();
	}

	bool foundSomething = false;
	if (currentBestNode) //We found the node to navigate. Move the cursor and we are done.
	{
		foundSomething = true;
		MoveMouseCursorToNode(currentBestNode, false);
	}
	else if(scrollIfElementNotFound)// Node is not found. 
	{
		// Based on the intended direction of movement, scroll so that some newer elements are visible.
		
		int cursorPosBeforeScrollX, cursorPosBeforeScrollY;
		mView->GetCursorPosition(cursorPosBeforeScrollX, cursorPosBeforeScrollY);

		switch(direction)
		{
		case EA::WebKit::JumpDown:
			{
				ScrollOnJump(true, -120, mJumpNavigationParams.mNumLinesToAutoScroll);
				break;
			}

		case EA::WebKit::JumpUp:
			{
				ScrollOnJump(true, 120, mJumpNavigationParams.mNumLinesToAutoScroll);
				break;
			}
		case EA::WebKit::JumpRight:
			{
				ScrollOnJump(false, -120, mJumpNavigationParams.mNumLinesToAutoScroll);
				break;
			}
		case EA::WebKit::JumpLeft:
			{
				ScrollOnJump(false, 120, mJumpNavigationParams.mNumLinesToAutoScroll);
				break;
			}
		default:
			{
				EAW_ASSERT_MSG(false, "Should not reach here\n");
			}
		}

		// We move the mouse cursor back to the location where the last best node was found. This is so that we don't end up with the cursor being in no man's land. While that may work 
		// for ordinary sites, it may not work well with customized pages that leverage CSS to visually indicate current position rather than a cursor graphic.
		// We don't call MoveMouseCursorToNode() with last cached node as there are edge cases where we may be holding an invalid node. Using a cached frame and checking against the
		// current valid frames safeguards against that.

		WebCore::IntSize scrollOffset;
		WebCore::Frame* pFrame1	= mView->GetFrame();
		while(pFrame1)
		{
			if(pFrame1 == mBestNodeFrame)//Find the frame where last best node existed.
			{
				if(pFrame1->view())
				{
					scrollOffset = pFrame1->view()->scrollOffset();//We read scroll offset here as it could have changed in the switch statement above.
					break;
				}
			}
			pFrame1 = pFrame1->tree()->traverseNext();
		}
		
		int targetcursorPosAfterScrollX, targetcursorPosAfterScrollY;
		targetcursorPosAfterScrollX = mBestNodeX + mBestNodeWidth / 2 - scrollOffset.width();
		targetcursorPosAfterScrollY = mBestNodeY + mBestNodeHeight/ 2 - scrollOffset.height();

		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.
		
		int width = mView->GetSize().mWidth;
		int height = mView->GetSize().mHeight;

		moveEvent.mX	= Clamp( cursorInset, targetcursorPosAfterScrollX, width - cursorInset );
		moveEvent.mY	= Clamp( cursorInset, targetcursorPosAfterScrollY, height - cursorInset );


		mView->OnMouseMoveEvent(moveEvent);
		// We intentionally don't call JumpToNearestElement(direction, false) here to avoid recursion. We do it in the overloaded function above.
	}
		
	return foundSomething;
}
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);

	}
}
void SelectionHandler::setSelection(WebCore::IntPoint start, WebCore::IntPoint end)
{
    m_selectionActive = true;

    ASSERT(m_webPage && m_webPage->mainFrame() && m_webPage->mainFrame()->selection());
    Frame* frame = m_webPage->mainFrame();
    ASSERT(frame);

#if SHOWDEBUG_SELECTIONHANDLER
    Olympia::Platform::log(Olympia::Platform::LogLevelInfo, "SelectionHandler::setSelection adjusted points %d, %d, %d, %d", start.x(), start.y(), end.x(), end.y());
#endif

    bool selectionIsValid = true;
    VisibleSelection newSelection(frame->visiblePositionForPoint(start), frame->visiblePositionForPoint(end));

    // Validate the new points to avoid crossing frame or editing boundaries.
    if (m_webPage->mainFrame() != m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->ownerRenderer()) {
        // Current focus frame is not the main frame, it must be a subframe.
        WebCore::IntRect subframeRect = m_webPage->focusedOrMainFrame()->ownerRenderer()->absoluteContentBox();
        if (!subframeRect.contains(start) || !subframeRect.contains(end)) {
            // Requested selection points are outside of current frame.
            selectionIsValid = false;
        }
    }
    // Check whether selection is occurring inside of an input field.  Do not handle as
    // an else if, an input field may be active inside of a subframe.
    if (m_webPage->m_inputHandler->isInputMode() && !selectionIsContainedByAnchorNode(newSelection)) {
        // Requested selection points are not contained within the anchor node (input field).
        selectionIsValid = false;
    }

    if (selectionIsValid) {
        frame->selection()->setSelection(newSelection);

#if SHOWDEBUG_SELECTIONHANDLER
        Olympia::Platform::log(Olympia::Platform::LogLevelInfo, "SelectionHandler::setSelection selection points valid, selection updated");
#endif
    }

    // Need to manually trigger notification as response to change.
    // This needs to be set even if no selection change occurs to ensure client has accurate
    // selection points.
    selectionPositionChanged();
}