#include "TextSelection.h"
#include "EditorState.h"
+#include "EwkViewImpl.h"
#include "NativeWebMouseEvent.h"
#include "ewk_view.h"
#include <Elementary.h>
namespace WebKit {
-TextSelection::TextSelection(Evas_Object* viewWidget, WebPageProxy* page, PageClientImpl* pageClient)
- : m_object(viewWidget),
- m_page(page),
- m_pageClient(pageClient),
- m_isTextSelectionDowned(false),
- m_isTextSelectionMode(false),
- m_isTextSelectionEnable(true),
- m_autoClearTextSelectionMode(true)
+TextSelection::TextSelection(EwkViewImpl* viewImpl)
+ : m_viewImpl(viewImpl)
+ , m_isTextSelectionDowned(false)
+ , m_isTextSelectionMode(false)
, m_moveAnimator(0)
+ , m_showTimer(0)
{
ASSERT(viewWidget);
- m_viewImpl = EwkViewImpl::fromEvasObject(m_object);
-
const Eina_List* defaultThemeList = elm_theme_list_get(0);
const Eina_List* l;
char* themePath = elm_theme_list_item_path_get((const char*)theme, 0);
if (themePath) {
- m_leftHandle = new TextSelectionHandle(m_object, themePath, "elm/entry/selection/block_handle_left", true, this);
- m_rightHandle = new TextSelectionHandle(m_object, themePath, "elm/entry/selection/block_handle_right", false, this);
+ m_leftHandle = new TextSelectionHandle(m_viewImpl->view(), themePath, "elm/entry/selection/block_handle_left", true, this);
+ m_rightHandle = new TextSelectionHandle(m_viewImpl->view(), themePath, "elm/entry/selection/block_handle_right", false, this);
free(themePath);
break;
}
}
- m_magnifier = new TextSelectionMagnifier(m_object, page, pageClient);
+ m_magnifier = new TextSelectionMagnifier(m_viewImpl);
- evas_object_event_callback_add(m_object, EVAS_CALLBACK_MOUSE_UP, onMouseUp, this);
+ evas_object_event_callback_add(m_viewImpl->view(), EVAS_CALLBACK_MOUSE_UP, onMouseUp, this);
}
TextSelection::~TextSelection()
delete m_magnifier;
- evas_object_event_callback_del(m_object, EVAS_CALLBACK_MOUSE_UP, onMouseUp);
+ evas_object_event_callback_del(m_viewImpl->view(), EVAS_CALLBACK_MOUSE_UP, onMouseUp);
}
void TextSelection::update()
{
- if (isTextSelectionMode() ) {
- EditorState editorState = m_page->editorState();
+ EditorState editorState = m_viewImpl->page()->editorState();
+ if (editorState.updateEditorRectOnly)
+ return;
+
+ if (isTextSelectionMode()) {
if (!editorState.selectionIsRange) {
- if (editorState.isContentEditable && !evas_object_focus_get(m_object)) {
+ if (editorState.isContentEditable && !evas_object_focus_get(m_viewImpl->view())) {
WebCore::IntRect caretRect;
- m_page->getCaretPosition(caretRect);
+ m_viewImpl->page()->getCaretPosition(caretRect);
if (!caretRect.isEmpty())
return;
} else {
WebCore::IntRect leftRect;
WebCore::IntRect rightRect;
- if (isTextSelectionDowned() || m_page->getSelectionHandlers(leftRect, rightRect))
+ if (isTextSelectionDowned() || m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect))
return;
setIsTextSelectionMode(false);
}
#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
- m_page->getTextStyleStateForSelection();
+ m_viewImpl->page()->getTextStyleStateForSelection();
#endif
} else {
if (!isTextSelectionDowned() && !isTextSelectionHandleDowned()) {
updateHandlers();
showContextMenu();
#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
- m_page->getTextStyleStateForSelection();
+ m_viewImpl->page()->getTextStyleStateForSelection();
#endif
}
}
}
#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
else {
- EditorState editorState = m_page->editorState();
if (editorState.isContentEditable && !editorState.selectionIsRange) {
WebCore::IntRect caretRect;
- m_page->getCaretPosition(caretRect);
+ m_viewImpl->page()->getCaretPosition(caretRect);
if (!caretRect.isEmpty()) {
- m_page->getTextStyleStateForSelection();
+ m_viewImpl->page()->getTextStyleStateForSelection();
}
}
}
void TextSelection::setIsTextSelectionMode(bool isTextSelectionMode)
{
- if (!autoClearTextSelectionMode())
+ if (!isAutomaticClearEnabled())
return;
if (!isTextSelectionMode) {
void TextSelection::clear()
{
- EditorState editorState = m_page->editorState();
+ EditorState editorState = m_viewImpl->page()->editorState();
if (!editorState.selectionIsRange)
return;
- m_page->executeEditCommand("Unselect");
+ m_viewImpl->page()->selectionRangeClear();
}
void TextSelection::hide()
void TextSelection::updateHandlers()
{
WebCore::IntRect leftRect, rightRect;
- if (!m_page->getSelectionHandlers(leftRect, rightRect)) {
- clear();
+ if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect))
return;
- }
+
+ m_lastLeftHandleRect = leftRect;
+ m_lastRightHandleRect = rightRect;
AffineTransform toEvasTransform = m_viewImpl->transformToScene();
WebCore::IntPoint leftEvasPoint = toEvasTransform.mapPoint(leftRect.minXMaxYCorner());
WebCore::IntPoint rightEvasPoint = toEvasTransform.mapPoint(rightRect.maxXMaxYCorner());
- EditorState editorState = m_page->editorState();
+ EditorState editorState = m_viewImpl->page()->editorState();
if (editorState.isContentEditable) {
m_leftHandle->hide();
m_rightHandle->hide();
WebCore::IntPoint editorRightEvasPoint = toEvasTransform.mapPoint(editorRect.maxXMaxYCorner());
int webViewX, webViewY, webViewWidth, webViewHeight;
- evas_object_geometry_get(m_object, &webViewX, &webViewY, &webViewWidth, &webViewHeight);
+ evas_object_geometry_get(m_viewImpl->view(), &webViewX, &webViewY, &webViewWidth, &webViewHeight);
if ((editorLeftEvasPoint.x() <= leftEvasPoint.x() && editorLeftEvasPoint.y() <= leftEvasPoint.y())
&& (webViewX <= leftEvasPoint.x() && webViewY <= leftEvasPoint.y())) {
m_leftHandle->move(leftEvasPoint);
void TextSelection::showContextMenu()
{
- if (!m_isTextSelectionEnable)
- return;
-
- EditorState editorState = m_page->editorState();
- if (editorState.isInPasswordField)
+ if (!isEnabled())
return;
+ EditorState editorState = m_viewImpl->page()->editorState();
if (!editorState.selectionIsRange && !editorState.isContentEditable)
return;
#endif
if (editorState.selectionIsRange) {
WebCore::IntRect leftRect, rightRect;
- if (!m_page->getSelectionHandlers(leftRect, rightRect)) {
- clear();
+ if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect))
return;
- }
+
#if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
// Checking if this point is in viewport area. If the calcualated
// point/Left/Right point are in view port then draw else do not draw the
// context menu. Only draw the selection points.
- FloatRect unscaledRect = FloatRect(m_pageClient->visibleContentRect());
- unscaledRect.scale(1 / m_pageClient->scaleFactor());
+ FloatRect unscaledRect = FloatRect(m_viewImpl->pageClient->visibleContentRect());
+ unscaledRect.scale(1 / m_viewImpl->pageClient->scaleFactor());
IntRect viewportRect = enclosingIntRect(unscaledRect);
WebCore::IntPoint visiblePoint = leftRect.center();
#endif
} else if (editorState.isContentEditable) {
WebCore::IntRect caretRect;
- m_page->getCaretPosition(caretRect);
+ m_viewImpl->page()->getCaretPosition(caretRect);
if (caretRect.isEmpty())
return;
// show context menu if its in viewport else do not show the contextmenu
- Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_object));
+ Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_viewImpl->view()));
if (!smartData || !smartData->api || !smartData->api->mouse_down || !smartData->api->mouse_up)
return;
point = m_viewImpl->transformToScene().mapPoint(point);
- Evas* evas = evas_object_evas_get(m_object);
+ Evas* evas = evas_object_evas_get(m_viewImpl->view());
// send mouse down.
Evas_Event_Mouse_Down mouseDown;
void TextSelection::hideContextMenu()
{
- if (!m_isTextSelectionEnable)
+ if (!isEnabled())
return;
- m_page->hideContextMenu();
+ m_viewImpl->page()->hideContextMenu();
}
void TextSelection::setLeftSelectionToEvasPoint(const IntPoint& evasPoint)
{
- m_page->setLeftSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
+ m_viewImpl->page()->setLeftSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
updateHandlers();
}
void TextSelection::setRightSelectionToEvasPoint(const IntPoint& evasPoint)
{
- m_page->setRightSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
+ m_viewImpl->page()->setRightSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
updateHandlers();
}
void TextSelection::handleMouseDown(TextSelectionHandle* handle, const IntPoint& /*position*/)
{
WebCore::IntPoint basePosition;
- EditorState editorState = m_page->editorState();
+ EditorState editorState = m_viewImpl->page()->editorState();
if (editorState.selectionIsRange) {
WebCore::IntRect leftRect, rightRect;
- if (!m_page->getSelectionHandlers(leftRect, rightRect)) {
+ if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect)) {
clear();
return;
}
hideMagnifier();
showContextMenu();
#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
- m_page->getTextStyleStateForSelection();
+ m_viewImpl->page()->getTextStyleStateForSelection();
#endif
}
void TextSelection::startMoveAnimator()
{
- if (!isTextSelectionEnable() || !isTextSelectionDowned())
+ if (!isEnabled() || !isTextSelectionDowned())
return;
if (!m_moveAnimator)
TextSelection* textSelection = static_cast<TextSelection*>(data);
Evas_Coord_Point point;
- evas_pointer_canvas_xy_get(evas_object_evas_get(textSelection->m_object), &point.x, &point.y);
+ evas_pointer_canvas_xy_get(evas_object_evas_get(textSelection->m_viewImpl->view()), &point.x, &point.y);
textSelection->textSelectionMove(IntPoint(point.x, point.y));
return ECORE_CALLBACK_RENEW;
}
// 'return false' means text selection is not possible for point.
-// 'return true' means text selection is possible, but it can be succeed or failed for some reason.
+// 'return true' means text selection is possible.
bool TextSelection::textSelectionDown(const IntPoint& point, bool isStartedTextSelectionFromOutside)
{
- setIsTextSelectionMode(false);
-
- IntPoint viewPoint = m_viewImpl->transformFromScene().mapPoint(point);
- WebHitTestResult::Data hitTestResultData;
-#if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
- hitTestResultData = m_pageClient->page()->hitTestResultAtPoint(viewPoint);
-#endif
-
- // If node under point has link, we can not process text selection.
- if (!hitTestResultData.absoluteImageURL.isEmpty()
-#if ENABLE(TIZEN_DRAG_SUPPORT)
- || hitTestResultData.isDragSupport
-#endif
- || !hitTestResultData.absoluteLinkURL.isEmpty()
- || !hitTestResultData.absoluteMediaURL.isEmpty())
+ // text selection should be ignored when longtap on handle from osp
+ if (!isEnabled() && isTextSelectionHandleDowned())
return false;
- // Process gesture_end(EWK_GESTURE_TAP) to activate the editing if node under point is editable.
- if (hitTestResultData.context & WebHitTestResult::HitTestResultContextEditable) {
- const Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_pageClient->viewWidget()));
- if (smartData->api && smartData->api->gesture_end) {
- Ewk_Event_Gesture gestureEvent = {EWK_GESTURE_TAP, {point.x(), point.y()}, {0, 0}, 0, 1, ecore_time_get() * 1000};
- smartData->api->gesture_end(const_cast<Ewk_View_Smart_Data*>(smartData), &gestureEvent);
- }
- }
+ setIsTextSelectionMode(false);
- bool result = m_page->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
+ IntPoint contentsPoint = m_viewImpl->transformFromScene().mapPoint(point);
+ bool result = m_viewImpl->page()->selectClosestWord(contentsPoint, isStartedTextSelectionFromOutside);
if (!result)
- return true;
+ return false;
if (isTextSelectionMode()) {
hide();
void TextSelection::textSelectionMove(const IntPoint& point, bool isStartedTextSelectionFromOutside)
{
+ // text selection should be ignored when longtap on handle from osp
+ if (!isEnabled() && isTextSelectionHandleDowned())
+ return;
+
if (!isTextSelectionMode()) {
stopMoveAnimator();
return;
}
- WebCore::IntPoint viewPoint = m_viewImpl->transformFromScene().mapPoint(point);
- m_page->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
-
- updateMagnifier(point);
+ WebCore::IntPoint viewPoint;
+ EditorState editorState = m_viewImpl->page()->editorState();
+ if (editorState.isContentEditable) {
+ IntRect mapRect = m_viewImpl->transformToScene().mapRect(editorState.editorRect);
+ IntPoint updatedPoint = point;
+ if ((point.y() < mapRect.y()) || (point.y() > ((mapRect.y()) + (mapRect.height()))))
+ updatedPoint.setY((mapRect.y()) + ((mapRect.height())/2) );
+
+ if (point.x() < mapRect.x()) {
+ updatedPoint.setX(mapRect.x());
+ if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionBackward))
+ updateMagnifier(updatedPoint);
+ } else if (point.x() > ((mapRect.x()) + (mapRect.width()))) {
+ updatedPoint.setX((mapRect.x()) + (mapRect.width()));
+ if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionForward))
+ updateMagnifier(updatedPoint);
+ } else {
+ viewPoint = m_viewImpl->transformFromScene().mapPoint(updatedPoint);
+ m_viewImpl->page()->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
+ updateMagnifier(updatedPoint);
+ }
+ } else {
+ viewPoint = m_viewImpl->transformFromScene().mapPoint(point);
+ m_viewImpl->page()->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
+ updateMagnifier(point);
+ }
showMagnifier();
}
void TextSelection::textSelectionUp(const IntPoint& point, bool isStartedTextSelectionFromOutside)
{
+ // text selection should be ignored when longtap on handle from osp
+ if (!isEnabled() && isTextSelectionHandleDowned())
+ return;
+
stopMoveAnimator();
- if (!isTextSelectionMode())
+ if (!isTextSelectionMode() || !isTextSelectionDowned())
return;
setIsTextSelectionDowned(false);
hideMagnifier();
- EditorState editorState = m_page->editorState();
+ EditorState editorState = m_viewImpl->page()->editorState();
if (editorState.selectionIsRange || editorState.isContentEditable) {
if (editorState.selectionIsRange)
updateHandlers();
setIsTextSelectionMode(false);
#if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
- m_page->getTextStyleStateForSelection();
+ m_viewImpl->page()->getTextStyleStateForSelection();
#endif
}
if (selectedHandle->isMouseDowned())
return;
}
-
- EditorState editorState = m_page->editorState();
- if (editorState.isContentEditable)
- setIsTextSelectionMode(false);
}
void TextSelection::textSelectionHandleMove(const IntPoint& position)
}
#endif
+bool TextSelection::isEnabled()
+{
+ return ewk_settings_text_selection_enabled_get(ewk_view_settings_get(m_viewImpl->view()));
+}
+
+bool TextSelection::isAutomaticClearEnabled()
+{
+ return ewk_settings_clear_text_selection_automatically_get(ewk_view_settings_get(m_viewImpl->view()));
+}
+
+void TextSelection::requestToShow()
+{
+ if (m_showTimer)
+ ecore_timer_del(m_showTimer);
+ m_showTimer = ecore_timer_loop_add((double)200.0/1000.0, showTimerCallback, this);
+}
+
+Eina_Bool TextSelection::showTimerCallback(void* data)
+{
+ TextSelection* textSelection = static_cast<TextSelection*>(data);
+ textSelection->showHandlesAndContextMenu();
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+void TextSelection::showHandlesAndContextMenu()
+{
+ WebCore::IntRect leftRect, rightRect;
+ if (m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect)) {
+ if ((leftRect == m_lastLeftHandleRect) && (rightRect == m_lastRightHandleRect)) {
+ if (m_showTimer) {
+ ecore_timer_del(m_showTimer);
+ m_showTimer = 0;
+ }
+
+ updateHandlesAndContextMenu(true);
+ }
+
+ m_lastLeftHandleRect = leftRect;
+ m_lastRightHandleRect = rightRect;
+ }
+}
+
} // namespace WebKit
#endif // TIZEN_WEBKIT2_TEXT_SELECTION