TizenRefApp-6936 [Email] Improve autoscrolling in Composer 28/83928/1
authorIgor Nazarov <i.nazarov@samsung.com>
Mon, 15 Aug 2016 17:00:50 +0000 (20:00 +0300)
committerIgor Nazarov <i.nazarov@samsung.com>
Mon, 15 Aug 2016 17:02:46 +0000 (20:02 +0300)
Change-Id: I526a9486440beb6c0f1a3b14dc48327bdc75bde3

modules/composer/inc/email-composer-initial-view.h
modules/composer/inc/email-composer-js.h
modules/composer/inc/email-composer-types.h
modules/composer/inc/email-composer.h
modules/composer/src/email-composer-initial-view.c
modules/composer/src/email-composer-webkit.c
res/misc/email-composer.js

index 7c36283..f13454a 100644 (file)
@@ -87,13 +87,13 @@ void composer_initial_view_cs_freeze_push(EmailComposerView *view);
 void composer_initial_view_cs_freeze_pop(EmailComposerView *view);
 
 /**
- * @brief Callback when coret position chenged
+ * @brief Callback when EWK selection changed
  * @param[in]  view»                  Email composer data
  * @param[in]  top»                   Top position value
  * @param[in]  bottom»                        Bottom position value
- * @param[in]  isCollapsed»   Is colapsed (hiden)
+ * @param[in]  flags           Flags (see ComposerSelectionEventFlag)
  */
-void composer_initial_view_caret_pos_changed_cb(EmailComposerView *view, int top, int bottom, bool isCollapsed);
+void composer_initial_view_ewk_selection_changed_cb(EmailComposerView *view, int top, int bottom, int flags);
 
 /**
  * @brief Callback when EWK View content height changed
index d41bb9c..8e1912b 100644 (file)
 #define EC_JS_GET_INITIAL_CONTENTS "GetComposedHtmlContents('0');"
 #define EC_JS_GET_COMPOSED_CONTENTS "GetComposedHtmlContents('%s');"
 
-#define EC_JS_NOTIFY_CARET_POS_CHANGE "NotifyCaretPosChange(true);"
+#define EC_JS_NOTIFY_SELECTION_CHANGE "NotifySelectionChange(%d);"
 
 #define EC_JS_SET_SCROLL_TOP "SetScrollTop(%d);"
 
index edc0a51..0546944 100644 (file)
@@ -52,7 +52,7 @@
 #define COMPOSER_EVENT_MAX_SIZE_EXCEEDED "max-size-exceeded"
 #define COMPOSER_EVENT_CHECKBOX_CLICKED "checkbox-clicked:"
 #define COMPOSER_EVENT_TEXT_STYLE_CHANGED "text-style-changed:"
-#define COMPOSER_EVENT_CARET_POS_CHANGED "caret-pos-changed:"
+#define COMPOSER_EVENT_EWK_SELECTION_CHANGED "selection-changed:"
 #define COMPOSER_EVENT_CONTENT_RESIZE "on-content-resize:"
 #define COMPOSER_EVENT_ON_DOM_SELECTED "on-dom-selected"
 #define COMPOSER_EVENT_ON_DOM_UNSELECTED "on-dom-unselected"
@@ -137,6 +137,26 @@ typedef enum {
 } ComposerCSEventFlag;
 
 /**
+ * @brief Composer CS selection events flags enum
+ */
+typedef enum {
+       /* Out flags */
+       COMPOSER_CS_SEF_COLLAPSED = 1,
+       COMPOSER_CS_SEF_IMAGE = 2,
+
+       /* Pass-through flags */
+       COMPOSER_CS_SEF_IMPORTANT = 4,
+       COMPOSER_CS_SEF_PREFER_BRING_IN = 8,
+
+       COMPOSER_CS_SEF_COLLAPSED_IMAGE =
+                       COMPOSER_CS_SEF_COLLAPSED | COMPOSER_CS_SEF_IMAGE,
+
+       COMPOSER_CS_SEF_IMPORTANT_COLLAPSED_IMAGE =
+                       COMPOSER_CS_SEF_IMPORTANT | COMPOSER_CS_SEF_COLLAPSED_IMAGE
+
+} ComposerCSSelectionEventFlag;
+
+/**
  * @brief Composer CS events masks enum
  */
 typedef enum {
index 8418056..ab00c70 100644 (file)
@@ -233,7 +233,6 @@ struct _view_data {
 
        /* etc */
        bool cs_ready;
-       bool cs_prefer_bringin;
        bool cs_bringin_to_ewk;
        bool cs_is_scrolling;
        Eina_Rectangle cs_ewk_visible_rect;
index f68f040..4b4cfc0 100644 (file)
@@ -68,7 +68,7 @@ static void _initial_view_cs_set_pos(EmailComposerView *view, int y);
 static void _initial_view_cs_handle_event(EmailComposerView *view, int event_mask);
 static void _initial_view_cs_update(EmailComposerView *view, int event_mask);
 
-static void _initial_view_cs_handle_caret_pos_change(EmailComposerView *view, int top, int bottom, bool isCollapsed);
+static void _initial_view_cs_handle_ewk_selection_change(EmailComposerView *view, int top, int bottom, int flags);
 static void _initial_view_cs_ensure_ewk_on_top(EmailComposerView *view, bool force_bring_in);
 
 static Eina_Bool _initial_view_cs_animator_cb(void *data, double pos);
@@ -434,6 +434,7 @@ static void _initial_view_cs_update(EmailComposerView *view, int event_mask)
        int new_scroll_pos = 0;
        bool need_set_pos = false;
        bool need_notify_caret_pos = false;
+       bool prefer_bringin = false;
 
        if (event_mask & COMPOSER_CSEF_INITIALIZE) {
                event_mask |= COMPOSER_CSEF_RESIZE_EVENTS;
@@ -453,11 +454,9 @@ static void _initial_view_cs_update(EmailComposerView *view, int event_mask)
                if (event_mask & COMPOSER_CSEF_MAIN_SCROLLER_RESIZE) {
                        evas_object_geometry_get(view->main_scroller, NULL, &view->cs_top, &view->cs_width, &view->cs_height);
                        need_notify_caret_pos = true;
+                       prefer_bringin = ((ecore_time_get() - view->cs_rotate_start_time) > CS_ROTATE_DURATION_SEC);
                }
 
-               view->cs_prefer_bringin = ((event_mask == COMPOSER_CSEF_MAIN_SCROLLER_RESIZE) &&
-                               ((ecore_time_get() - view->cs_rotate_start_time) > CS_ROTATE_DURATION_SEC));
-
                if (event_mask & COMPOSER_CSEF_MAIN_BOX_RESIZE) {
                        if (view->richtext_toolbar) {
                                evas_object_geometry_get(view->richtext_toolbar, NULL, NULL, NULL, &view->cs_rttb_height);
@@ -501,7 +500,11 @@ static void _initial_view_cs_update(EmailComposerView *view, int event_mask)
                Ecore_IMF_Input_Panel_State imf_state = ecore_imf_context_input_panel_state_get(ctx);
                ecore_imf_context_del(ctx);
                if (imf_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
-                       ewk_view_script_execute(view->ewk_view, EC_JS_NOTIFY_CARET_POS_CHANGE, NULL, NULL);
+                       char script[EMAIL_BUFF_SIZE_BIG] = { 0 };
+                       snprintf(script, EMAIL_BUFF_SIZE_BIG, EC_JS_NOTIFY_SELECTION_CHANGE,
+                                       COMPOSER_CS_SEF_IMPORTANT |
+                                       (prefer_bringin ? COMPOSER_CS_SEF_PREFER_BRING_IN : 0));
+                       ewk_view_script_execute(view->ewk_view, script, NULL, NULL);
                }
        }
 
@@ -510,10 +513,12 @@ static void _initial_view_cs_update(EmailComposerView *view, int event_mask)
        }
 }
 
-static void _initial_view_cs_handle_caret_pos_change(EmailComposerView *view, int top, int bottom, bool isCollapsed)
+static void _initial_view_cs_handle_ewk_selection_change(EmailComposerView *view, int top, int bottom, int flags)
 {
        debug_enter();
 
+       bool isCollapsed = ((flags & COMPOSER_CS_SEF_COLLAPSED) != 0);
+
        if (!isCollapsed) {
                _initial_view_cs_stop_all(view); // TODO temp fix. Need replace when selection handler event added
        }
@@ -523,8 +528,16 @@ static void _initial_view_cs_handle_caret_pos_change(EmailComposerView *view, in
                return;
        }
 
+       if ((flags & COMPOSER_CS_SEF_IMPORTANT_COLLAPSED_IMAGE) == COMPOSER_CS_SEF_IMAGE) {
+               debug_log("Skipping not important not collapsed image selection change.");
+               return;
+       }
+
+       bool prefer_bringin = ((flags & COMPOSER_CS_SEF_PREFER_BRING_IN) != 0);
+
        int caret_padding = CS_CARET_PADDING1_PX;
-       if (!isCollapsed) {
+       if (((flags & COMPOSER_CS_SEF_COLLAPSED_IMAGE) == COMPOSER_CS_SEF_COLLAPSED_IMAGE) ||
+               ((flags & COMPOSER_CS_SEF_COLLAPSED_IMAGE) == 0)) {
                caret_padding = CS_CARET_PADDING2_PX;
        }
 
@@ -554,7 +567,7 @@ static void _initial_view_cs_handle_caret_pos_change(EmailComposerView *view, in
                        new_scroll_pos = view->cs_edge_scroll_pos;
                }
 
-               if (view->cs_prefer_bringin && isCollapsed) {
+               if (prefer_bringin && isCollapsed) {
                        composer_initial_view_cs_bring_in(view, new_scroll_pos);
                } else {
                        composer_initial_view_cs_show(view, new_scroll_pos);
@@ -562,15 +575,13 @@ static void _initial_view_cs_handle_caret_pos_change(EmailComposerView *view, in
 
                view->cs_bringin_to_ewk = false;
 
-       } else if (view->cs_prefer_bringin && view->cs_bringin_to_ewk) {
+       } else if (prefer_bringin && view->cs_bringin_to_ewk) {
                if (view->cs_scroll_pos < view->cs_edge_scroll_pos) {
                        composer_initial_view_cs_bring_in(view, view->cs_edge_scroll_pos);
                }
                view->cs_bringin_to_ewk = false;
        }
 
-       view->cs_prefer_bringin = false;
-
        debug_leave();
 }
 
@@ -946,12 +957,12 @@ void composer_initial_view_set_combined_scroller_rotation_mode(void *data)
        debug_leave();
 }
 
-void composer_initial_view_caret_pos_changed_cb(EmailComposerView *view, int top, int bottom, bool isCollapsed)
+void composer_initial_view_ewk_selection_changed_cb(EmailComposerView *view, int top, int bottom, int flags)
 {
        retm_if(!view->cs_ready, "Not ready!");
 
        if (elm_object_focus_get(view->ewk_btn)) {
-               _initial_view_cs_handle_caret_pos_change(view, top, bottom, isCollapsed);
+               _initial_view_cs_handle_ewk_selection_change(view, top, bottom, flags);
        }
 }
 
index 07eb3a5..15d974f 100644 (file)
@@ -544,12 +544,12 @@ static void _ewk_view_handle_user_event(EmailComposerView *view, const char *eve
                                        debug_error("_webkit_parse_text_style_changed_data failed!");
                                }
                        }
-               } else if (g_str_has_prefix(event, COMPOSER_EVENT_CARET_POS_CHANGED)) {
+               } else if (g_str_has_prefix(event, COMPOSER_EVENT_EWK_SELECTION_CHANGED)) {
                        int top = 0;
                        int bottom = 0;
-                       int isCollapsed = 0;
-                       if (sscanf(event + strlen(COMPOSER_EVENT_CARET_POS_CHANGED), "%d%d%d", &top, &bottom, &isCollapsed) == 3) {
-                               composer_initial_view_caret_pos_changed_cb(view, top, bottom, (isCollapsed != 0));
+                       int flags = 0;
+                       if (sscanf(event + strlen(COMPOSER_EVENT_EWK_SELECTION_CHANGED), "%d%d%d", &top, &bottom, &flags) == 3) {
+                               composer_initial_view_ewk_selection_changed_cb(view, top, bottom, flags);
                        }
                } else if (g_str_has_prefix(event, COMPOSER_EVENT_CONTENT_RESIZE)) {
                        int height = 0;
index 93f3686..c76a567 100644 (file)
@@ -37,6 +37,11 @@ var FontSize = {
        "7": 48
 };
 
+var G_ENUM_SEF_COLLAPSED = 1;
+var G_ENUM_SEF_IMAGE = 2;
+var G_ENUM_SEF_IMPORTANT = 4;
+var G_ENUM_SEF_PREFER_BRING_IN = 8;
+
 /* Define names */
 var G_ENABLE_DEBUG_LOGS = false;
 
@@ -215,13 +220,13 @@ utils.log("==> screen.width:" + screen.width);
 utils.log("==> window.innerWidth:" + window.innerWidth);
 utils.log("==> window.devicePixelRatio:" + window.devicePixelRatio);
 
-function CaretPos(top, bottom, isCollapsed) {
+function SelectionPos(top, bottom, flags) {
        this.top = Math.round(top);
        this.bottom = Math.round(bottom);
-       this.isCollapsed = isCollapsed;
+       this.flags = flags;
 
        this.toString = function () {
-               return this.top + " " + this.bottom + " " + this.isCollapsed;
+               return this.top + " " + this.bottom + " " + this.flags;
        };
 }
 
@@ -327,10 +332,10 @@ function OnKeyDown(obj, event) {
        }
 }
 
-function NotifyCaretPosChange(force) {
-       var caretPos = GetCaretPosition(force);
+function NotifySelectionChange(flags) {
+       var caretPos = GetSelectionPos(flags & (G_ENUM_SEF_IMPORTANT | G_ENUM_SEF_PREFER_BRING_IN));
        if (caretPos) {
-               utils.sendUserEvent("caret-pos-changed:" + caretPos);
+               utils.sendUserEvent("selection-changed:" + caretPos);
        }
 }
 
@@ -459,6 +464,8 @@ function ImageLayer() {
                element_.style.display = "initial";
 
                updatePosition();
+
+               NotifySelectionChange(0);
        }
 
        function deactivate() {
@@ -469,12 +476,16 @@ function ImageLayer() {
                if (element_.parentElement !== document.body) {
                        document.body.appendChild(element_);
                }
+
+               NotifySelectionChange(0);
        }
 
        function updatePosition() {
                /** @type {HTMLElement} */
                var parent = null;
 
+               var targetClientRect = targetElement_.getBoundingClientRect();
+
                if (!isDragging_) {
                        parent = targetElement_.parentElement;
                        while (true) {
@@ -488,25 +499,26 @@ function ImageLayer() {
                                parent = parent.parentElement;
                        }
 
+                       var offsetClientRect = parent.getBoundingClientRect();
+
                        if (window.getComputedStyle(parent).position === "static") {
                                parent.style.position = "relative";
                        }
 
-               } else if (window.getComputedStyle(document.body).position !== "static") {
-                       parent = document.body;
-               } else {
-                       parent = document.documentElement;
-               }
+                       if (element_.parentElement !== parent) {
+                               parent.appendChild(element_);
+                       }
 
-               if (element_.parentElement !== parent) {
-                       parent.appendChild(element_);
-               }
+                       element_.style.position = "absolute";
+                       element_.style.left = (targetClientRect.left - offsetClientRect.left) + "px";
+                       element_.style.top = (targetClientRect.top - offsetClientRect.top) + "px";
 
-               var targetClientRect = targetElement_.getBoundingClientRect();
-               var offsetClientRect = parent.getBoundingClientRect();
+               } else {
+                       element_.style.position = "fixed";
+                       element_.style.left = targetClientRect.left + "px";
+                       element_.style.top = targetClientRect.top + "px";
+               }
 
-               element_.style.left = (targetClientRect.left - offsetClientRect.left) + "px";
-               element_.style.top = (targetClientRect.top - offsetClientRect.top) + "px";
                element_.style.width = targetClientRect.width + "px";
                element_.style.height = targetClientRect.height + "px";
        }
@@ -744,7 +756,7 @@ function animationStepCb(timestamp) {
 
                utils.sendUserEvent("on-content-resize:" + height * G_VAL_PIXEL_RATIO);
 
-               NotifyCaretPosChange(true);
+               NotifySelectionChange(G_ENUM_SEF_IMPORTANT);
        }
 
        g_frameFlags = 0;
@@ -1139,9 +1151,8 @@ function GetComposedHtmlContents(inlineImageSrcs) {
        return dstContent.outerHTML;
 }
 
-function GetCaretPosition(force) {
+function GetSelectionPos(flags) {
        var rect;
-       var isCollapsed = 1;
 
        var lastRange = g_lastRange;
        g_lastRange = null;
@@ -1149,7 +1160,11 @@ function GetCaretPosition(force) {
        var range = utils.getSelectionRange();
 
        if (range) {
-               isCollapsed = range.collapsed ? 1 : 0;
+               if (range.collapsed) {
+                       flags |= G_ENUM_SEF_COLLAPSED;
+               } else {
+                       g_lastRange = range;
+               }
                var rects = range.getClientRects();
                if (rects.length > 0) {
                        if (lastRange) {
@@ -1157,12 +1172,11 @@ function GetCaretPosition(force) {
                                        g_lastRangeIsForward = false;
                                } else if (range.compareBoundaryPoints(Range.END_TO_END, lastRange) != 0) {
                                        g_lastRangeIsForward = true;
-                               } else if (!force && !isCollapsed) {
+                               } else if (!(flags & (G_ENUM_SEF_COLLAPSED | G_ENUM_SEF_IMPORTANT))) {
                                        return null;
                                }
                        }
                        rect = rects[g_lastRangeIsForward ? (rects.length - 1) : 0];
-                       g_lastRange = range;
                } else {
                        var span = document.createElement("span");
                        span.style.position = "absolute";
@@ -1178,7 +1192,7 @@ function GetCaretPosition(force) {
                }
        } else {
                var goodNode = true;
-               var node = (force && g_imageLayer.getActiveImage());
+               var node = g_imageLayer.getActiveImage();
                if (!node) {
                        node = document.activeElement;
                        goodNode = (node.id === G_NAME_ORG_MESSAGE_BAR_CHECKBOX);
@@ -1191,16 +1205,20 @@ function GetCaretPosition(force) {
                }
        }
 
+       if (g_imageLayer.getActiveImage()) {
+               flags |= G_ENUM_SEF_IMAGE;
+       }
+
        if (!rect) {
                return null;
        }
 
        var scrollY = window.scrollY;
 
-       return new CaretPos(
+       return new SelectionPos(
                (rect.top + scrollY) * G_VAL_PIXEL_RATIO,
                (rect.bottom + scrollY) * G_VAL_PIXEL_RATIO,
-               isCollapsed);;
+               flags);
 }
 
 function RestoreCurrentSelection() {
@@ -1237,7 +1255,7 @@ function OnSelectionChanged() {
        }
 
        NotifyFontStyleChange(false);
-       NotifyCaretPosChange(false);
+       NotifySelectionChange(0);
 }
 
 function GetComputedStyle(el) {