Refactor disambiguation popup
authorDongjun Kim <djmix.kim@samsung.com>
Sun, 2 Nov 2014 09:53:00 +0000 (18:53 +0900)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
Previous implementation of disambiguation popup was buggy. It was
scaling already scaled image. It was scaling without keeping aspect
ratio. It caused lot of bugs with clicked position and rendering.
To tests the new implementation on desktop please make sure to add
--touch-events flag to efl_webview_app startup parameters.

Original patch : http://165.213.202.130:8080/#/c/70671
Original Author : Kamil Klimek <k.klimek@partner.samsung.com>

Together with : I5e0cf66df8922f8d4523b950bbcc999a7b90b402
Bug: http://107.108.218.239/bugzilla/show_bug.cgi?id=8405
Reviewed by: Kamil Klimek, Piotr Tworek, SeungSeop Park, Viatcheslav Ostapenko

Change-Id: I1563a1cc2f722866ae9be0aa5f73440fcb8d5d25
Signed-off-by: Dongjun Kim <djmix.kim@samsung.com>
Signed-off-by: hh4813.kim <hh4813.kim@samsung.com>
tizen_src/impl/browser/disambiguation_popup_efl.cc [new file with mode: 0644]
tizen_src/impl/browser/disambiguation_popup_efl.h [new file with mode: 0644]
tizen_src/impl/browser/renderer_host/render_widget_host_view_efl.cc
tizen_src/impl/browser/renderer_host/render_widget_host_view_efl.h
tizen_src/impl/browser/renderer_host/web_event_factory_efl.cc
tizen_src/impl/browser/renderer_host/web_event_factory_efl.h
tizen_src/impl/chromium-efl.gyp
tizen_src/impl/eweb_view.cc
tizen_src/impl/resource/DisambiguationPopup.edc [new file with mode: 0644]
tizen_src/packaging/chromium-efl.spec

diff --git a/tizen_src/impl/browser/disambiguation_popup_efl.cc b/tizen_src/impl/browser/disambiguation_popup_efl.cc
new file mode 100644 (file)
index 0000000..9ab6be6
--- /dev/null
@@ -0,0 +1,202 @@
+// Copyright 2014 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "browser/disambiguation_popup_efl.h"
+
+#include "base/path_service.h"
+#include "base/files/file_path.h"
+#include "browser/renderer_host/render_widget_host_view_efl.h"
+#include "ui/events/event.h"
+#include "ui/gfx/screen.h"
+#include "paths_efl.h"
+
+#include <Elementary.h>
+
+#if defined(OS_TIZEN_MOBILE)
+#include <dlfcn.h>
+#include <efl_assist.h>
+extern void* EflAssistHandle;
+#endif
+
+namespace content {
+
+namespace {
+#if defined(OS_TIZEN_MOBILE)
+void _back_hard_key_cb(void* data, Evas_Object* obj, void*) {
+  DisambiguationPopupEfl* instance = static_cast<DisambiguationPopupEfl*>(data);
+  instance->Dismiss();
+}
+#endif
+
+void _OnMouseUp(void* data, Evas*, Evas_Object* image, void* eventInfo) {
+  Evas_Event_Mouse_Up* up_event =
+      static_cast<Evas_Event_Mouse_Up*>(eventInfo);
+
+  DisambiguationPopupEfl* disambiguation_popup =
+      static_cast<DisambiguationPopupEfl*>(data);
+  disambiguation_popup->HandleMouseEventUp(up_event);
+  disambiguation_popup->Dismiss();
+}
+
+void _OnMouseDown(void* data, Evas*,Evas_Object* image, void* eventInfo) {
+  Evas_Event_Mouse_Down* down_event =
+      static_cast<Evas_Event_Mouse_Down*>(eventInfo);
+  DisambiguationPopupEfl* disambiguation_popup =
+      static_cast<DisambiguationPopupEfl*>(data);
+  disambiguation_popup->HandleMouseEventDown(down_event);
+}
+
+} // namespace
+
+DisambiguationPopupEfl::DisambiguationPopupEfl(
+    Evas_Object* parent_view, RenderWidgetHostViewEfl* rwhv)
+    : rwhv_(rwhv)
+    , parent_view_(parent_view)
+    , content_image_(NULL)
+    , popup_(NULL) {
+  CHECK(parent_view);
+  CHECK(rwhv);
+
+  popup_ = elm_ctxpopup_add(parent_view);
+  Elm_Theme* theme = elm_theme_new();
+  base::FilePath edje_path;
+  base::FilePath link_magnifier_edj;
+  PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edje_path);
+  link_magnifier_edj = edje_path.Append(FILE_PATH_LITERAL("DisambiguationPopup.edj"));
+  elm_theme_ref_set(theme, elm_theme_default_get());
+  elm_theme_extension_add(theme, link_magnifier_edj.AsUTF8Unsafe().c_str());
+  elm_object_theme_set(popup_, theme);
+  elm_theme_free(theme);
+
+  elm_ctxpopup_hover_parent_set(popup_, parent_view);
+  elm_ctxpopup_direction_priority_set(popup_, ELM_CTXPOPUP_DIRECTION_UP,
+      ELM_CTXPOPUP_DIRECTION_DOWN, ELM_CTXPOPUP_DIRECTION_UP,
+      ELM_CTXPOPUP_DIRECTION_DOWN);
+  evas_object_smart_callback_add(popup_, "dismissed", Dismissed, this);
+}
+
+DisambiguationPopupEfl::~DisambiguationPopupEfl() {
+  Clear();
+  evas_object_del(popup_);
+  popup_ = NULL;
+}
+
+void DisambiguationPopupEfl::Show(const gfx::Rect& target,
+                                  const SkBitmap& display_image) {
+  Dismiss();
+
+  target_rect_ = target;
+
+  if (content_image_)
+    evas_object_del(content_image_);
+  content_image_ = evas_object_image_add(evas_object_evas_get(parent_view_));
+  elm_object_content_set(popup_, content_image_);
+
+#if defined(OS_TIZEN_MOBILE)
+  if (EflAssistHandle) {
+    typedef void (*cb_type)(Evas_Object*, Ea_Callback_Type, Ea_Event_Cb func, void*);
+    cb_type cb = (cb_type)dlsym(EflAssistHandle, "ea_object_event_callback_add");
+    (*cb)(popup_, EA_CALLBACK_BACK, _back_hard_key_cb, this);
+  }
+#endif
+
+  UpdateImage(display_image);
+
+  evas_object_event_callback_add(content_image_,
+      EVAS_CALLBACK_MOUSE_UP, _OnMouseUp, this);
+  evas_object_event_callback_add(content_image_,
+      EVAS_CALLBACK_MOUSE_DOWN, _OnMouseDown, this);
+
+  int parent_view_x = 0, parent_view_y = 0;
+  evas_object_geometry_get(parent_view_, &parent_view_x, &parent_view_y, 0, 0);
+
+  const gfx::Point position = target_rect_.CenterPoint();
+  evas_object_move(popup_, position.x() + parent_view_x,
+      position.y() + parent_view_y);
+
+  evas_object_show(popup_);
+}
+
+void DisambiguationPopupEfl::Dismiss() {
+  if (!IsVisible())
+    return;
+
+  target_rect_ = gfx::Rect();
+  elm_ctxpopup_dismiss(popup_);
+  Clear();
+}
+
+void DisambiguationPopupEfl::UpdateImage(const SkBitmap& display_image) {
+  DCHECK(content_image_);
+
+  width_ = display_image.width();
+  height_ = display_image.height();
+
+  // TODO: should be set to same as display_image colorspace
+  evas_object_image_colorspace_set(content_image_, EVAS_COLORSPACE_ARGB8888);
+
+  evas_object_image_alpha_set(content_image_, EINA_TRUE);
+  evas_object_image_filled_set(content_image_, EINA_FALSE);
+
+  evas_object_image_size_set(content_image_, width_, height_);
+  evas_object_image_data_copy_set(content_image_, display_image.getPixels());
+
+  evas_object_image_fill_set(content_image_, 0, 0, width_, height_);
+  evas_object_size_hint_min_set(content_image_, width_, height_);
+  evas_object_size_hint_max_set(content_image_, width_, height_);
+  evas_object_size_hint_padding_set(content_image_, 0, 0, 0, 0);
+}
+
+void DisambiguationPopupEfl::Clear() {
+  evas_object_hide(popup_);
+  elm_object_content_unset(popup_);
+  if (content_image_) {
+    evas_object_del(content_image_);
+    content_image_ = NULL;
+  }
+}
+
+bool DisambiguationPopupEfl::IsVisible() {
+  return evas_object_visible_get(popup_);
+}
+
+void DisambiguationPopupEfl::HandleMouseEventUp(Evas_Event_Mouse_Up* up_event) {
+  HandleMouseEvent(up_event);
+}
+
+void DisambiguationPopupEfl::HandleMouseEventDown(Evas_Event_Mouse_Down* down_event) {
+  HandleMouseEvent(down_event);
+}
+
+template<class T>
+void DisambiguationPopupEfl::HandleMouseEvent(T* event) {
+
+  int image_x = 0, image_y = 0;
+  evas_object_geometry_get(content_image_, &image_x, &image_y, 0, 0);
+
+  int image_cord_x = event->canvas.x - image_x;
+  int image_cord_y = event->canvas.y - image_y;
+
+  // we have image cords, now we need to translate them to target_rect_
+  float ratio = static_cast<float>(width_) / target_rect_.width();
+
+  int target_rect_x = target_rect_.x() + (image_cord_x / ratio);
+  int target_rect_y = target_rect_.y() + (image_cord_y / ratio);
+
+  int parent_view_x = 0, parent_view_y = 0;
+  evas_object_geometry_get(parent_view_, &parent_view_x, &parent_view_y, 0, 0);
+  float device_scale_factor = rwhv_->device_scale_factor();
+  event->canvas.x = target_rect_x + (parent_view_x * device_scale_factor);
+  event->canvas.y = target_rect_y + (parent_view_y * device_scale_factor);
+
+  rwhv_->HandleEvasEvent(event);
+}
+
+void DisambiguationPopupEfl::Dismissed(void* data, Evas_Object*, void*) {
+  DisambiguationPopupEfl* disambiguation_popup =
+      static_cast<DisambiguationPopupEfl*>(data);
+  disambiguation_popup->Clear();
+}
+
+}
diff --git a/tizen_src/impl/browser/disambiguation_popup_efl.h b/tizen_src/impl/browser/disambiguation_popup_efl.h
new file mode 100644 (file)
index 0000000..e522808
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2014 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DISAMBIGUATION_POPUP_EFL_H
+#define DISAMBIGUATION_POPUP_EFL_H
+
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+
+#include <Evas.h>
+
+class SkBitmap;
+
+namespace content {
+
+class RenderWidgetHostViewEfl;
+
+class DisambiguationPopupEfl {
+ public:
+  DisambiguationPopupEfl(Evas_Object* parent_view, RenderWidgetHostViewEfl*);
+  ~DisambiguationPopupEfl();
+
+  void Show(const gfx::Rect& target, const SkBitmap& display_image);
+  void Dismiss();
+
+  bool IsVisible();
+
+  void SetImageSize(int&, int&, int, int, const gfx::Point&);
+  void UpdateImage(const SkBitmap& display_image);
+  void Clear();
+
+  void HandleMouseEventUp(Evas_Event_Mouse_Up* up_event);
+  void HandleMouseEventDown(Evas_Event_Mouse_Down* down_event);
+
+ private:
+  template<class T>
+  void HandleMouseEvent(T* event);
+
+  static void Dismissed(void*, Evas_Object*, void*);
+
+  gfx::Rect target_rect_;
+
+  RenderWidgetHostViewEfl* rwhv_;
+  Evas_Object* parent_view_;
+  // Image displayed on popup
+  Evas_Object* content_image_;
+  Evas_Object* popup_;
+
+  int height_;
+  int width_;
+
+  DISALLOW_COPY_AND_ASSIGN(DisambiguationPopupEfl);
+};
+
+} // namespace content
+
+#endif
index 5bd69c1..e3780db 100644 (file)
@@ -13,9 +13,9 @@
 #include "base/debug/trace_event.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
-
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
+#include "browser/disambiguation_popup_efl.h"
 #include "browser/renderer_host/im_context_efl.h"
 #include "browser/renderer_host/scroll_detector.h"
 #include "browser/renderer_host/web_event_factory_efl.h"
@@ -58,6 +58,7 @@
 #include <Ecore_Evas.h>
 #include <Ecore_Input.h>
 #include <Ecore_X.h>
+#include <Elementary.h>
 
 #define EFL_MAX_WIDTH 10000
 #define EFL_MAX_HEIGHT 10000  // borrowed from GTK+ port
@@ -128,6 +129,8 @@ RenderWidgetHostViewEfl::RenderWidgetHostViewEfl(RenderWidgetHost* widget, EWebV
   }
 
   gesture_recognizer_->AddGestureEventHelper(this);
+
+  disambiguation_popup_.reset(new DisambiguationPopupEfl(content_image_, this));
 }
 
 RenderWidgetHostViewEfl::~RenderWidgetHostViewEfl() {
@@ -596,6 +599,8 @@ void RenderWidgetHostViewEfl::UpdateCursor(const WebCursor& webcursor) {
 void RenderWidgetHostViewEfl::SetIsLoading(bool is_loading) {
   is_loading_ = is_loading;
   UpdateCursor(WebCursor());
+  if (disambiguation_popup_)
+    disambiguation_popup_->Dismiss();
 }
 
 void RenderWidgetHostViewEfl::TextInputTypeChanged(ui::TextInputType type,
@@ -698,7 +703,7 @@ void RenderWidgetHostViewEfl::DidStopFlinging() {
 }
 
 void RenderWidgetHostViewEfl::ShowDisambiguationPopup(const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
-  NOTIMPLEMENTED();
+  disambiguation_popup_->Show(rect_pixels, zoomed_bitmap);
 }
 
 bool RenderWidgetHostViewEfl::CanDispatchToConsumer(ui::GestureConsumer* consumer) {
@@ -1069,6 +1074,10 @@ void RenderWidgetHostViewEfl::HandleEvasEvent(const Evas_Event_Mouse_Wheel* even
 void RenderWidgetHostViewEfl::HandleEvasEvent(const Evas_Event_Key_Down* event) {
   bool wasFiltered = false;
 
+  if (WebEventFactoryEfl::isHardwareBackKey(event) && disambiguation_popup_) {
+    disambiguation_popup_->Dismiss();
+  }
+
   if (!strcmp(event->key, "XF86Phone")) {
     host_->WasHidden();
   }
@@ -1199,6 +1208,16 @@ void RenderWidgetHostViewEfl::HandleGesture(ui::GestureEvent* event) {
 
   blink::WebGestureEvent gesture = content::MakeWebGestureEventFromUIEvent(*event);
 
+  if (event->type() == ui::ET_GESTURE_TAP ||
+      event->type() == ui::ET_GESTURE_TAP_CANCEL) {
+      float size = 32.0f; //Default value
+#if defined(OS_TIZEN_MOBILE)
+      size = elm_config_finger_size_get() / device_scale_factor();
+#endif
+      gesture.data.tap.width = size;
+      gesture.data.tap.height = size;
+  }
+
   gesture.x = event->x();
   gesture.y = event->y();
 
index d44a7c0..ac30a44 100644 (file)
@@ -50,6 +50,7 @@ class ScrollDetector;
 
 namespace content {
 
+class DisambiguationPopupEfl;
 class IMContextEfl;
 class RenderWidgetHostImpl;
 class RenderWidgetHostView;
@@ -144,15 +145,14 @@ class RenderWidgetHostViewEfl
   virtual void ResizeCompositingSurface(const gfx::Size&);
   virtual void RenderProcessGone(base::TerminationStatus, int) override;
   virtual bool OnMessageReceived(const IPC::Message&) override;
+
   void OnFilteredMessageReceived(const IPC::Message&);
 
   virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo&, InputEventAckState) override;
   virtual void DidStopFlinging() override;
 
-#if defined(TOOLKIT_VIEWS) || defined(USE_AURA)
   virtual void ShowDisambiguationPopup(const gfx::Rect& rect_pixels,
                                        const SkBitmap& zoomed_bitmap) override;
-#endif
 
   virtual void OnSwapCompositorFrame(
       uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) override;
@@ -302,6 +302,8 @@ class RenderWidgetHostViewEfl
   // In Aura GestureRecognizer is global. Should we follow that?
   scoped_ptr<ui::GestureRecognizer> gesture_recognizer_;
 
+  scoped_ptr<DisambiguationPopupEfl> disambiguation_popup_;
+
   int current_orientation_;
 
   Evas_GL* evas_gl_;
index 69fbe2b..9855356 100644 (file)
@@ -320,4 +320,11 @@ ui::TouchEvent WebEventFactoryEfl::toUITouchEvent(const tizen_webview::Touch_Poi
                         p->id, base::TimeDelta::FromMilliseconds(ecore_time_get() * 1000));
 }
 
+bool WebEventFactoryEfl::isHardwareBackKey(const Evas_Event_Key_Down* event) {
+#if defined(OS_TIZEN)
+  return (strcmp(event->key, "XF86Stop") == 0);
+#endif
+  return (strcmp(event->key, "Escape") == 0);
+}
+
 }
index 3b6b0fe..2d12469 100644 (file)
@@ -28,6 +28,7 @@ class WebEventFactoryEfl {
   static content::NativeWebKeyboardEvent toWebKeyboardEvent(Evas*, const Evas_Event_Key_Up*);
 
   static ui::TouchEvent toUITouchEvent(const tizen_webview::Touch_Point*, Evas_Object* evas_object, float scale_factor);
+  static bool isHardwareBackKey(const Evas_Event_Key_Down* event);
 };
 
 }
index 06e21dc..bb4926f 100644 (file)
@@ -97,6 +97,8 @@
       'browser/device_sensors/data_fetcher_impl_tizen.cc',
       'browser/device_sensors/data_fetcher_impl_tizen.h',
       'browser/device_sensors/data_fetcher_shared_memory_tizen.cc',
+      'browser/disambiguation_popup_efl.cc',
+      'browser/disambiguation_popup_efl.h',
       'browser/download_manager_delegate_efl.cc',
       'browser/download_manager_delegate_efl.h',
       'browser/favicon/favicon_commands.cc',
index f1de228..a8b459c 100644 (file)
@@ -274,9 +274,6 @@ void EWebView::Initialize() {
 #ifdef TIZEN_EDGE_EFFECT
   edge_effect_ = EdgeEffect::create(evas_object_);
 #endif
-#if defined(TIZEN_POPUPZOOMER_SUPPORT)
-  disambiguation_popup_controller_.reset(new content::DisambiguationPopupControllerEfl(this));
-#endif
 
   if (contents_for_new_window_) {
      web_contents_.reset(contents_for_new_window_);
diff --git a/tizen_src/impl/resource/DisambiguationPopup.edc b/tizen_src/impl/resource/DisambiguationPopup.edc
new file mode 100644 (file)
index 0000000..1955b1a
--- /dev/null
@@ -0,0 +1,270 @@
+collections {
+    group {
+        name: "elm/ctxpopup/bg/default";
+        parts {
+            part {
+                name: "bg";
+                type: RECT;
+                mouse_events: 1;
+                description {
+                    state: "default" 0.0;
+                    visible: 0;
+                }
+                description {
+                    state: "visible" 0.0;
+                    color: 0 0 0 80;
+                    visible: 1;
+                }
+            }
+        }
+        programs {
+            program {
+                name: "clicked_event";
+                signal: "mouse,clicked,1";
+                source: "bg";
+                action: SIGNAL_EMIT "elm,action,click" "";
+            }
+            program {
+                name: "show";
+                signal: "elm,state,show";
+                source: "elm";
+                action: STATE_SET "visible" 0.0;
+                target: "bg";
+            }
+            program {
+                name: "hide";
+                signal: "elm,state,hide";
+                source: "elm";
+                action: STATE_SET "default" 0.0;
+                target: "bg";
+            }
+        }
+    }
+
+    group {
+        name: "elm/ctxpopup/base/default";
+        parts {
+            #define CTXPOPUP_SHADOW_LEFT_PADDING 14
+            #define CTXPOPUP_SHADOW_RIGHT_PADDING 14
+            #define CTXPOPUP_SHADOW_TOP_PADDING 14
+            #define CTXPOPUP_SHADOW_BOTTOM_PADDING 14
+            #define CTXPOPUP_ARROW_SIZE_INC 36 36
+
+            part {
+                name: "frame_shadow_left_top_padding";
+                type: SPACER;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    min: CTXPOPUP_SHADOW_LEFT_PADDING CTXPOPUP_SHADOW_TOP_PADDING;
+                    max: CTXPOPUP_SHADOW_LEFT_PADDING CTXPOPUP_SHADOW_TOP_PADDING;
+                    rel2 { relative: 0 0; }
+                    align: 0 0;
+                    fixed: 1 1;
+                }
+            }
+            part {
+                name: "frame_shadow_right_bottom_padding";
+                type: SPACER;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    min: CTXPOPUP_SHADOW_RIGHT_PADDING CTXPOPUP_SHADOW_BOTTOM_PADDING;
+                    max: CTXPOPUP_SHADOW_RIGHT_PADDING CTXPOPUP_SHADOW_BOTTOM_PADDING;
+                    rel1 { relative: 1 1; }
+                    align: 1 1;
+                    fixed: 1 1;
+                }
+            }
+            part {
+                name: "ctxpopup_frame_left_top";
+                type: SPACER;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    align: 0 0;
+                    fixed: 1 1;
+                    min: 1 1;
+                    max: 1 1;
+                    rel1 { relative: 1 1; to: "frame_shadow_left_top_padding"; }
+                }
+            }
+            part {
+                name: "ctxpopup_frame_right_bottom";
+                type: SPACER;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    align: 1 1;
+                    fixed: 1 1;
+                    min: 1 1;
+                    max: 1 1;
+                    rel2 { relative: 0 0; to: "frame_shadow_right_bottom_padding"; }
+                }
+            }
+            part {
+                name: "arrow_area_up";
+                type: SPACER;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    min: CTXPOPUP_ARROW_SIZE_INC;
+                    fixed: 1 1;
+                    align: 0.5 1;
+                    rel1 {
+                        relative: 1 1;
+                        to_x: "ctxpopup_frame_left_top";
+                        to_y: "ctxpopup_frame_left_top";
+                    }
+                    rel2 {
+                        relative: 0 1;
+                        to_x: "ctxpopup_frame_right_bottom";
+                        to_y: "ctxpopup_frame_left_top";
+                    }
+                }
+            }
+            part {
+                name: "arrow_area_down";
+                type: SPACER;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    min: CTXPOPUP_ARROW_SIZE_INC;
+                    fixed: 1 1;
+                    align: 0.5 0;
+                    rel1 {
+                        relative: 1 0;
+                        to_x: "ctxpopup_frame_left_top";
+                        to_y: "ctxpopup_frame_right_bottom";
+                    }
+                    rel2 {
+                        relative: 0 0;
+                        to_x: "ctxpopup_frame_right_bottom";
+                        to_y: "ctxpopup_frame_right_bottom";
+                    }
+                }
+            }
+            part {
+                name: "elm.swallow.arrow_up";
+                type: SWALLOW;
+                mouse_events: 0;
+                scale: 1;
+                dragable {
+                    x: 1 1 0;
+                    y: 1 1 0;
+                    confine: "arrow_area_up";
+                }
+                description {
+                    state: "default" 0.0;
+                    min: CTXPOPUP_ARROW_SIZE_INC;
+                    fixed: 1 1;
+                    visible: 1;
+                }
+            }
+            part {
+                name: "elm.swallow.arrow_down";
+                type: SWALLOW;
+                mouse_events: 0;
+                scale: 1;
+                dragable {
+                    x: 1 1 0;
+                    y: 1 1 0;
+                    confine: "arrow_area_down";
+                }
+                description {
+                    state: "default" 0.0;
+                    min: CTXPOPUP_ARROW_SIZE_INC;
+                    fixed: 1 1;
+                    visible: 1;
+                }
+            }
+            part {
+                name: "arrow_area_left";
+                type: SPACER;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    min: CTXPOPUP_ARROW_SIZE_INC;
+                    fixed: 1 1;
+                    align: 1 0.5;
+                    rel1 {
+                        relative: 1 1;
+                        to_x: "ctxpopup_frame_left_top";
+                        to_y: "ctxpopup_frame_left_top";
+                    }
+                    rel2 {
+                        relative: 1 0;
+                        to_x: "ctxpopup_frame_left_top";
+                        to_y: "ctxpopup_frame_right_bottom";
+                    }
+                }
+            }
+            part {
+                name: "arrow_area_right";
+                type: SPACER;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    min: CTXPOPUP_ARROW_SIZE_INC;
+                    fixed: 1 1;
+                    align: 0 0.5;
+                    rel1 {
+                        relative: 0 1;
+                        to_x: "ctxpopup_frame_right_bottom";
+                        to_y: "ctxpopup_frame_left_top";
+                    }
+                    rel2 {
+                        relative: 0 0;
+                        to_x: "ctxpopup_frame_right_bottom";
+                        to_y: "ctxpopup_frame_right_bottom";
+                    }
+                }
+            }
+            part {
+                name: "elm.swallow.arrow_left";
+                type: SWALLOW;
+                mouse_events: 0;
+                scale: 1;
+                dragable {
+                    x: 1 1 0;
+                    y: 1 1 0;
+                    confine: "arrow_area_left";
+                }
+                description {
+                    state: "default" 0.0;
+                    min: CTXPOPUP_ARROW_SIZE_INC;
+                    fixed: 1 1;
+                    visible: 1;
+                }
+            }
+            part {
+                name: "elm.swallow.arrow_right";
+                type: SWALLOW;
+                mouse_events: 0;
+                scale: 1;
+                dragable {
+                    x: 1 1 0;
+                    y: 1 1 0;
+                    confine: "arrow_area_right";
+                }
+                description {
+                    state: "default" 0.0;
+                    min: CTXPOPUP_ARROW_SIZE_INC;
+                    fixed: 1 1;
+                    visible: 1;
+                }
+            }
+            part {
+                name: "elm.swallow.content";
+                type: SWALLOW;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    align: 0 0;
+                    rel1 { to: "frame_shadow_left_top_padding"; relative: 1 1; }
+                    rel2 { to: "frame_shadow_right_bottom_padding"; relative: 0 0; }
+                }
+            }
+        }
+    }
+}
index 0e75c25..cc71f07 100755 (executable)
@@ -22,7 +22,7 @@ Source0: %{name}-%{version}.tar.gz
 Requires(post): /sbin/ldconfig
 Requires(post): xkeyboard-config
 Requires(postun): /sbin/ldconfig
-BuildRequires: which, vi, python, python-xml, bison, flex, gperf, gettext, perl, edje-bin
+BuildRequires: which, vi, python, python-xml, bison, flex, gperf, gettext, perl, edje-tools
 BuildRequires: libjpeg-turbo-devel, expat-devel, libhaptic, libcap-devel
 BuildRequires: pkgconfig(glesv2)
 BuildRequires: pkgconfig(libpulse)