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 5bd69c1a75fc352afdf0fd0732526f92d090e059..e3780dbfcf154c47cb2167e2d67d229c9441ed7d 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 d44a7c09d0924f381453b87b8ea2eefd986d973f..ac30a4423e28c0dbe85d8a9e32341c37f0bad5ab 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 69fbe2ba8edb6f5801a18388840e60e1cc894d8e..9855356feff4346b8b00db3e1c6db676779131ad 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 3b6b0feaa543020ff16ece00554f87ec8838a1e0..2d12469615f76f1ede418c148c141417bf0b0171 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 06e21dcf297e84c35599d4c88450ff90f251b01d..bb4926f0e7ccb0add48ab5a55c5d8fb1a34c0161 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 f1de228937d9198a1d59da2f010bbdfd207ba36e..a8b459c58652829d038fc9a0e128b74d09bccd78 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 0e75c258016be61d7057c264c984d06016901899..cc71f079ea1a1fc68e9de75ff58b27d73baf03a5 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)