Implement input field zoom animation
authorbunam.jeon <bunam.jeon@samsung.com>
Fri, 16 Aug 2013 07:37:27 +0000 (16:37 +0900)
committerbunam.jeon <bunam.jeon@samsung.com>
Fri, 23 Aug 2013 05:11:55 +0000 (14:11 +0900)
[Title] Implement input field zoom animation
[Issue#] N/A
[Problem] N/A
[Cause] No Implementation
[Solution] New Implementation

Change-Id: I1ffbac7e508cc63108b0b61ec4a6492def354fec

Source/WTF/wtf/Platform.h
Source/WebKit2/PlatformTizen.cmake
Source/WebKit2/UIProcess/API/efl/EwkViewImpl.cpp
Source/WebKit2/UIProcess/API/efl/EwkViewImpl.h
Source/WebKit2/UIProcess/API/efl/ewk_view.cpp
Source/WebKit2/UIProcess/API/efl/tizen/InputFieldZoom.cpp [new file with mode: 0755]
Source/WebKit2/UIProcess/API/efl/tizen/InputFieldZoom.h [new file with mode: 0755]
Source/WebKit2/UIProcess/efl/InputMethodContextEfl.cpp

index 3cdf60d..d45c90e 100755 (executable)
@@ -682,6 +682,7 @@ com) : Patch to do not adjust cover rect as fixed pixel size*/
 #define ENABLE_TIZEN_WEBKIT2_FOR_MOVING_TEXT_SELECTION_HANDLE_FROM_OSP 1 /* Yuni Jeong(yhnet.jung@samsung.com) : Patchs for moving text selection handle from OSP */
 #define ENABLE_TIZEN_WEBKIT2_FIX_INVAlID_SCROLL_FOR_NEW_PAGE 1 /* Jongseok Yang (js45.yang@samsung.com) : Patch to fix the invalid scroll position by open source patch */
 #define ENABLE_TIZEN_WEBKIT2_TEXT_SELECTION_NOT_PAINT_SELECTION_FOR_INPUTBOX 1 /* Prathmesh Manurkar(prathmesh.m@samsung.com) : Patch for not painting the selection for Contents Inside the input.Selection is not painted when the focus in outside the input box */
+#define ENABLE_TIZEN_WEBKIT2_INPUT_FIELD_ZOOM 1 /* Bunam Jeon(bunam.jeon@samsung.com) : Implement input field zoom animation */
 #endif /* ENABLE(TIZEN_WEBKIT2) */
 
 /* When displaying menu list using menu icon, a additional scrollbar is displayed in the screen center
index 841aff3..5663545 100755 (executable)
@@ -107,6 +107,7 @@ LIST(APPEND WebKit2StaticForDebug_SOURCES
     UIProcess/API/efl/tizen/AutoFillPopup.cpp
     UIProcess/API/efl/tizen/GestureClient.cpp
     UIProcess/API/efl/tizen/GestureRecognizer.cpp
+    UIProcess/API/efl/tizen/InputFieldZoom.cpp
     UIProcess/API/efl/tizen/InputPicker.cpp
     UIProcess/API/efl/tizen/JavaScriptPopup.cpp
     UIProcess/API/efl/tizen/LinkMagnifierProxy.cpp
index 4152198..cd66b32 100755 (executable)
@@ -209,6 +209,10 @@ EwkViewImpl::EwkViewImpl(Evas_Object* view)
     gestureClient = GestureClient::create(this);
 #endif
 
+#if ENABLE(TIZEN_WEBKIT2_INPUT_FIELD_ZOOM)
+    inputFieldZoom = InputFieldZoom::create(this);
+#endif
+
 #if ENABLE(TIZEN_WEBKIT2_TILED_SCROLLBAR)
     const char* hideScrollbar = getenv("TIZEN_WEBKIT2_TILED_SCROLLBAR_HIDE");
     if (hideScrollbar && atoi(hideScrollbar) == 1)
index fd78c49..fdf861a 100755 (executable)
 #include "GestureClient.h"
 #endif
 
+#if ENABLE(TIZEN_WEBKIT2_INPUT_FIELD_ZOOM)
+#include "InputFieldZoom.h"
+#endif
+
 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
 #include "InputPicker.h"
 #endif
@@ -444,6 +448,10 @@ public:
     bool holdVerticalPanning;
 #endif // #if ENABLE(TIZEN_GESTURE)
 
+#if ENABLE(TIZEN_WEBKIT2_INPUT_FIELD_ZOOM)
+    OwnPtr<WebKit::InputFieldZoom> inputFieldZoom;
+#endif
+
 #if ENABLE(TIZEN_WEBKIT2_TILED_SCROLLBAR)
     bool mainFrameScrollbarVisibility;
 #endif
index e580674..b46a1c8 100755 (executable)
@@ -2538,25 +2538,6 @@ bool ewk_view_focused_node_adjust(Evas_Object* ewkView, Eina_Bool adjustForExter
     EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false);
     EWK_VIEW_IMPL_GET_OR_RETURN(smartData, impl, false);
 
-    double scaleFactor = impl->pageClient->scaleFactor();
-    IntSize contentsSize = impl->pageProxy->contentsSize();
-
-    double newScaleFactor = scaleFactor;
-    // Readable zoom value is dependent on device DPI
-    if (scaleFactor < impl->pageProxy->deviceScaleFactor()
-        && impl->pageClient->viewportConstraints().userScalable)
-        newScaleFactor = impl->pageProxy->deviceScaleFactor();
-
-    // Readable zoom value should be inside of viewport scale range
-    newScaleFactor = impl->pageClient->adjustScaleWithViewport(newScaleFactor);
-
-    // scale contents' size with new scale factor
-#if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
-    contentsSize.scale(newScaleFactor);
-#else
-    contentsSize.scale(newScaleFactor / scaleFactor);
-#endif
-
 #if ENABLE(TIZEN_ISF_PORT)
     // We should treat both of ECORE_IMF_INPUT_PANEL_STATE_SHOW and ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW
     // as IME is shown. ECORE_IMF_INPUT_PANEL_STATE_HIDE is ignored at here.
@@ -2565,8 +2546,8 @@ bool ewk_view_focused_node_adjust(Evas_Object* ewkView, Eina_Bool adjustForExter
     // 2. external keyboard is not connected(if adjustForExternalKeyboard is true)
     // 3. imfContext is null(if adjustForExternalKeyboard is false)
     // 4. input panel state is hidden(if adjustForExternalKeyboard is false)
+
     if ((!(static_cast<PageClient*>(impl->pageClient.get()))->isViewFocused()
-        || (adjustForExternalKeyboard && !InputMethodContextEfl::shouldUseExternalKeyboard())
         || (!adjustForExternalKeyboard && !impl->inputMethodContext())
         || (!adjustForExternalKeyboard && !impl->inputMethodContext()->isShow()))
 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
@@ -2580,41 +2561,14 @@ bool ewk_view_focused_node_adjust(Evas_Object* ewkView, Eina_Bool adjustForExter
     // we need to consider it.
     IntRect selectionRect = impl->pageProxy->editorState().selectionRect;
     IntRect focusedNodeRect = impl->pageClient->focusedNodeRect();
-#if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
-    selectionRect.scale(newScaleFactor);
-    focusedNodeRect.scale(newScaleFactor);
-#else
-    selectionRect.scale(newScaleFactor / scaleFactor);
-    focusedNodeRect.scale(newScaleFactor / scaleFactor);
-#endif
+
     if (selectionRect.isEmpty())
         return false;
 
-    IntRect visibleRect = impl->pageClient->visibleContentRect();
-    IntPoint scrollPosition = visibleRect.location();
-    // Do not adjust scroll position if content is userscalable or selection rect (caret) is visible after scaling
-    if (impl->pageClient->userScalable() || !visibleRect.contains(selectionRect)) {
-        // set paddings
-        scrollPosition = IntPoint(selectionRect.x() - visibleRect.width() / 3, selectionRect.y() - visibleRect.height() / 3);
-        // If both input field's position x and selection rect can be displayed together,
-        // adjust scroll position to input field's position x.
-        if (!focusedNodeRect.isEmpty() && selectionRect.x() - focusedNodeRect.x() < visibleRect.width() * 4 / 5)
-            scrollPosition.setX(focusedNodeRect.x());
-    }
-
-#if ENABLE(TIZEN_DLOG_SUPPORT)
-    TIZEN_LOGI("scroll position: [%d, %d], scale factor: [%.2f]", scrollPosition.x(), scrollPosition.y(), newScaleFactor);
+#if ENABLE(TIZEN_WEBKIT2_INPUT_FIELD_ZOOM)
+    impl->inputFieldZoom->startInputFieldZoom(impl->transformFromScene().mapPoint(IntPoint(focusedNodeRect.x(), focusedNodeRect.y())) ,focusedNodeRect);
 #endif
 
-#if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
-    impl->pageClient->setVisibleContentRect(IntRect(scrollPosition, impl->size()), newScaleFactor);
-#else
-    if (newScaleFactor != scaleFactor)
-        impl->pageProxy->scalePage(newScaleFactor, scrollPosition);
-    else
-        impl->pageProxy->scrollMainFrameTo(scrollPosition);
-#endif
-    evas_object_move(smartData->image, smartData->view.x, smartData->view.y);
     return true;
 }
 
diff --git a/Source/WebKit2/UIProcess/API/efl/tizen/InputFieldZoom.cpp b/Source/WebKit2/UIProcess/API/efl/tizen/InputFieldZoom.cpp
new file mode 100755 (executable)
index 0000000..0220be7
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(TIZEN_WEBKIT2_INPUT_FIELD_ZOOM)
+#include "InputFieldZoom.h"
+#include "EwkViewImpl.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+static const int s_numberOfCosineValue = 17;
+static const int s_inputFieldWidthMargin = 4;
+static const float s_inputFieldMaxScaleFactor = 2.5;
+static const float s_cosine[s_numberOfCosineValue] =
+{ 1.0f, 0.99f, 0.96f, 0.93f, 0.88f, 0.82f, 0.75f, 0.67f, 0.59f, 0.5f, 0.41f, 0.33f, 0.25f, 0.18f, 0.12f, 0.07f, 0.01f };
+
+
+static void viewRenderPreCallback(void* data, Evas*, void*)
+{
+    InputFieldZoom* inputFieldZoom = static_cast<InputFieldZoom*>(data);
+    if (inputFieldZoom->isWorking()) {
+        if (inputFieldZoom->m_isScaleFactorChanged)
+            inputFieldZoom->m_isScaleFactorChanged = false;
+        else
+            inputFieldZoom->process();
+    }
+}
+
+static Eina_Bool scaleAnimatorCallback(void* data)
+{
+    static_cast<InputFieldZoom*>(data)->m_isScaleFactorChanged = true;
+
+    return static_cast<InputFieldZoom*>(data)->process();
+}
+
+
+
+InputFieldZoom::InputFieldZoom(EwkViewImpl* viewImpl)
+    : m_scaleAnimator(0)
+    , m_scaleIndex(0)
+    , m_targetScale(0)
+    , m_isWorking(false)
+    , m_isScaleFactorChanged(false)
+    , m_viewImpl(viewImpl)
+{
+    evas_event_callback_add(evas_object_evas_get(m_viewImpl->view()), EVAS_CALLBACK_RENDER_PRE, viewRenderPreCallback, this);
+}
+
+InputFieldZoom::~InputFieldZoom()
+{
+    if (m_scaleAnimator) {
+        ecore_animator_del(m_scaleAnimator);
+        m_scaleAnimator = 0;
+    }
+    evas_event_callback_del_full(evas_object_evas_get(m_viewImpl->view()), EVAS_CALLBACK_RENDER_PRE, viewRenderPreCallback, this);
+}
+
+void InputFieldZoom:: startInputFieldZoom(const IntPoint& target, const IntRect& area)
+{
+    if (area.isEmpty())
+        return;
+
+    m_isWorking = true;
+
+    PageClientImpl* pageClientImpl = m_viewImpl->pageClient.get();
+    EINA_SAFETY_ON_NULL_RETURN(pageClientImpl);
+    EINA_SAFETY_ON_NULL_RETURN(m_viewImpl->page());
+
+    FloatRect targetRect = area;
+    targetRect.inflateX(s_inputFieldWidthMargin);
+    FloatRect viewportRect(FloatPoint(), m_viewImpl->page()->viewSize());
+    m_targetScale = pageClientImpl->adjustScaleWithViewport(viewportRect.width() / targetRect.width());
+    FloatRect newContentsRect;
+
+    if (m_targetScale > s_inputFieldMaxScaleFactor)
+        m_targetScale = s_inputFieldMaxScaleFactor;
+
+    newContentsRect = FloatRect(targetRect.center(), FloatSize(viewportRect.width() / m_targetScale, viewportRect.height() / m_targetScale));
+    if (targetRect.height() > newContentsRect.height())
+        newContentsRect.setY(target.y());
+    newContentsRect.move(-newContentsRect.width() / 2, -newContentsRect.height() / 2);
+    newContentsRect.setLocation(pageClientImpl->boundContentsPositionAtScale(newContentsRect.location(), m_targetScale));
+
+    FloatRect currentContentsRect = m_viewImpl->transformFromView().mapRect(viewportRect);
+    m_baseRect = currentContentsRect;
+    m_targetRect = newContentsRect;
+    m_scaleIndex = s_numberOfCosineValue - 1;
+
+#if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
+    if (m_scaleAnimator)
+        ecore_animator_del(m_scaleAnimator);
+    m_scaleAnimator = ecore_animator_add(scaleAnimatorCallback, this);
+    process();
+#else
+    IntPoint scrollPosition(m_targetRect.x() * m_targetScale, m_targetRect.y() * m_targetScale);
+    m_viewImpl->page()->scale(m_targetScale, scrollPosition);
+#endif
+}
+
+bool InputFieldZoom::process()
+{
+    PageClientImpl* pageClientImpl = m_viewImpl->pageClient.get();
+    EINA_SAFETY_ON_NULL_RETURN_VAL(pageClientImpl, false);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(m_viewImpl->page(), false);
+
+    FloatRect rect;
+    float multiplier = s_cosine[m_scaleIndex--];
+    rect.setX(m_baseRect.x() + (m_targetRect.x() - m_baseRect.x()) * multiplier);
+    rect.setY(m_baseRect.y() + (m_targetRect.y() - m_baseRect.y()) * multiplier);
+    rect.setWidth(m_baseRect.width() + (m_targetRect.width() - m_baseRect.width()) * multiplier);
+    rect.setHeight(m_baseRect.height() + (m_targetRect.height() - m_baseRect.height()) * multiplier);
+
+    float scaleFactor = m_viewImpl->page()->viewSize().width() / rect.width();
+    IntPoint scrollPosition(rect.x() * scaleFactor, rect.y() * scaleFactor);
+    m_viewImpl->page()->scaleImage(scaleFactor, scrollPosition);
+
+    if (m_scaleIndex < 0)
+        stop();
+
+    return true;
+}
+
+void InputFieldZoom::stop()
+{
+    if (!m_isWorking)
+        return;
+
+    if (m_scaleAnimator) {
+        ecore_animator_del(m_scaleAnimator);
+        m_scaleAnimator = 0;
+    }
+    PageClientImpl* pageClientImpl = m_viewImpl->pageClient.get();
+    EINA_SAFETY_ON_NULL_RETURN(pageClientImpl);
+    EINA_SAFETY_ON_NULL_RETURN(m_viewImpl->page());
+
+    float scaleFactor = m_viewImpl->page()->viewSize().width() / m_targetRect.width();
+    IntPoint scrollPosition(m_targetRect.x() * scaleFactor, m_targetRect.y() * scaleFactor);
+    m_viewImpl->page()->scale(scaleFactor, scrollPosition);
+    m_isWorking = false;
+}
+
+bool InputFieldZoom::isWorking()
+{
+    return m_isWorking;
+}
+} // namespace WebKit
+#endif // TIZEN_WEBKIT2_INPUT_FIELD_ZOOM
diff --git a/Source/WebKit2/UIProcess/API/efl/tizen/InputFieldZoom.h b/Source/WebKit2/UIProcess/API/efl/tizen/InputFieldZoom.h
new file mode 100755 (executable)
index 0000000..23411aa
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef InputFieldZoom_h
+#define InputFieldZoom_h
+
+#if ENABLE(TIZEN_WEBKIT2_INPUT_FIELD_ZOOM)
+#include <Ecore.h>
+#include <Evas.h>
+#include <WebCore/IntRect.h>
+#include <WebCore/IntPoint.h>
+
+class EwkViewImpl;
+
+namespace WebKit {
+
+class InputFieldZoom {
+public:
+    static PassOwnPtr<InputFieldZoom> create(EwkViewImpl* viewImpl)
+    {
+        return adoptPtr(new InputFieldZoom(viewImpl));
+    }
+    ~InputFieldZoom();
+
+    void startInputFieldZoom(const WebCore::IntPoint& target, const WebCore::IntRect& area);
+    void stop();
+    bool isWorking();
+    bool process();
+
+    bool m_isScaleFactorChanged;
+
+private:
+    explicit InputFieldZoom(EwkViewImpl*);
+
+    EwkViewImpl* m_viewImpl;
+    Ecore_Animator* m_scaleAnimator;
+    WebCore::FloatRect m_baseRect;
+    WebCore::FloatRect m_targetRect;
+    int m_scaleIndex;
+    float m_targetScale;
+    bool m_isWorking;
+};
+
+} // namespace WebKit
+#endif // TIZEN_WEBKIT2_INPUT_FIELD_ZOOM
+#endif // InputFieldZoom_h
\ No newline at end of file
index cd58699..745b03a 100755 (executable)
@@ -722,13 +722,18 @@ void InputMethodContextEfl::showIMFContext(const EditorState& editor, bool isUse
         m_viewImpl->pageClient->closeClipboardWindow();
 #endif
 
+     // input field zoom for external keyboard
+    if (s_shouldUseExternalKeyboard)
+        ewk_view_focused_node_adjust(m_viewImpl->view(), EINA_TRUE);
+    else {
+        if (isShow())
+            ewk_view_focused_node_adjust(m_viewImpl->view(), EINA_FALSE);
+    }
+
     resetIMFContext();
     ecore_imf_context_focus_in(m_context.get());
     ecore_imf_context_input_panel_show(m_context.get());
 
-    // input field zoom for external keyboard
-    ewk_view_focused_node_adjust(m_viewImpl->view(), EINA_TRUE);
-
     setKeyboardMode(true);
 }