[bugfix:S1976, 1123, 1204] copy & paste popup is not displaying
[framework/uifw/elementary.git] / src / modules / ctxpopup_copypasteUI / copypaste.c
1 #include <Elementary.h>
2 #include "elm_module_priv.h"
3 #include "elm_priv.h"
4 #include <appsvc/appsvc.h>
5
6 #define MULTI_(id) dgettext("sys_string", #id)
7 #define S_SELECT MULTI_(IDS_COM_SK_SELECT)
8 #define S_SELECT_ALL MULTI_(IDS_COM_BODY_SELECT_ALL)
9 #define S_COPY MULTI_(IDS_COM_BODY_COPY)
10 #define S_CUT MULTI_(IDS_COM_BODY_CUT)
11 #define S_PASTE MULTI_(IDS_COM_BODY_PASTE)
12 #define S_CLIPBOARD MULTI_(IDS_COM_BODY_CLIPBOARD)
13
14
15 Elm_Entry_Extension_data *ext_mod;
16 static int _mod_hook_count = 0;
17
18 typedef struct _Elm_Entry_Context_Menu_Item Elm_Entry_Context_Menu_Item;
19 struct _Elm_Entry_Context_Menu_Item
20 {
21    Evas_Object *obj;
22    const char *label;
23    const char *icon_file;
24    const char *icon_group;
25    Elm_Icon_Type icon_type;
26    Evas_Smart_Cb func;
27    void *data;
28 };
29
30 static void _ctxpopup_hide(Evas_Object *popup);
31 static void _ctxpopup_position(Evas_Object *obj);
32 static void
33 _entry_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
34 {
35    if (evas_pointer_button_down_mask_get(e))
36      _ctxpopup_hide(ext_mod->popup);
37    else
38      _ctxpopup_position(data);
39 }
40
41 static void
42 _ctxpopup_hide(Evas_Object *popup)
43 {
44    evas_object_hide(popup);
45    evas_object_event_callback_del(ext_mod->caller, EVAS_CALLBACK_MOVE, _entry_move);
46    ext_mod->caller = NULL;
47 }
48
49 static void
50 _ctxpopup_position(Evas_Object *obj)
51 {
52    if(!ext_mod) return;
53
54    Evas_Coord cx, cy, cw, ch, x, y, w, h;
55    if (!edje_object_part_text_selection_geometry_get(ext_mod->ent, "elm.text", &x, &y, &w, &h))
56      {
57         evas_object_geometry_get(ext_mod->ent, &x, &y, NULL, NULL);
58         edje_object_part_text_cursor_geometry_get(ext_mod->ent, "elm.text",
59                                                   &cx, &cy, &cw, &ch);
60         evas_object_size_hint_min_get(ext_mod->popup, &w, &h);
61         if (cw < w)
62           {
63              cx += (cw - w) / 2;
64              cw = w;
65           }
66         if (ch < h)
67           {
68              cy += (ch - h) / 2;
69              ch = h;
70           }
71         evas_object_move(ext_mod->popup, x + cx, y + cy);
72         evas_object_resize(ext_mod->popup, cw, ch);
73      }
74    else
75      {
76         if (ext_mod->viewport_rect.x != -1 || ext_mod->viewport_rect.y != -1
77             || ext_mod->viewport_rect.w != -1 || ext_mod->viewport_rect.h != -1)
78           {
79              Evas_Coord vx, vy, vw, vh, x2, y2;
80              x2 = x + w;
81              y2 = y + h;
82              vx = ext_mod->viewport_rect.x;
83              vy = ext_mod->viewport_rect.y;
84              vw = ext_mod->viewport_rect.w;
85              vh = ext_mod->viewport_rect.h;
86
87              if (x < vx) x = vx;
88              if (y < vy) y = vy;
89              if (x2 > vx + vw) x2 = vx + vw;
90              if (y2 > vy + vh) y2 = vy + vh;
91              w = x2 - x;
92              h = y2 - y;
93           }
94         else
95           {
96              Evas_Coord sw, sh, x2, y2;
97              x2 = x + w;
98              y2 = y + h;
99              ecore_x_window_size_get(ecore_x_window_root_first_get(), &sw, &sh);
100
101              if (x < 0) x = 0;
102              if (y < 0) y = 0;
103              if (x2 > sw) x2 = sw;
104              if (y2 > sh) y2 = sh;
105              w = x2 - x;
106              h = y2 - y;
107           }
108         cx = x + (w / 2);
109         cy = y + (h / 2);
110         evas_object_move(ext_mod->popup, cx, cy);
111      }
112 }
113
114 static void
115 _select_all(void *data, Evas_Object *obj, void *event_info)
116 {
117    if(!ext_mod) return;
118
119    ext_mod->selectall(data,obj,event_info);
120    _ctxpopup_hide(obj);
121 }
122
123 static void
124 _select(void *data, Evas_Object *obj, void *event_info)
125 {
126    if(!ext_mod) return;
127
128    ext_mod->select(data,obj,event_info);
129    _ctxpopup_hide(obj);
130 }
131
132 static void
133 _paste(void *data, Evas_Object *obj, void *event_info)
134 {
135    if(!ext_mod) return;
136
137    ext_mod->paste(data,obj,event_info);
138    _ctxpopup_hide(obj);
139 }
140
141 static void
142 _cut(void *data, Evas_Object *obj, void *event_info)
143 {
144    if(!ext_mod) return;
145
146    ext_mod->cut(data,obj,event_info);
147    _ctxpopup_hide(obj);
148    elm_object_scroll_freeze_pop(ext_mod->popup);
149 }
150
151 static void
152 _copy(void *data, Evas_Object *obj, void *event_info)
153 {
154    if(!ext_mod) return;
155
156    ext_mod->copy(data,obj,event_info);
157    _ctxpopup_hide(obj);
158    elm_object_scroll_freeze_pop(ext_mod->popup);
159 }
160
161 static void
162 _cancel(void *data, Evas_Object *obj, void *event_info)
163 {
164    if(!ext_mod) return;
165
166    ext_mod->cancel(data,obj,event_info);
167    _ctxpopup_hide(obj);
168    elm_object_scroll_freeze_pop(ext_mod->popup);
169 }
170
171 static void
172 _search_menu(void *data, Evas_Object *obj, void *event_info)
173 {
174    if(!ext_mod) return;
175
176    int ret;
177    bundle *b = bundle_create();
178    if (!b)
179      {
180         //printf("bundle_create() failed\n");
181         return;
182      }
183
184    appsvc_set_operation(b, APPSVC_OPERATION_SEARCH);
185    if (ext_mod->selmode)
186      {
187         char *selection = elm_entry_selection_get(ext_mod->caller);
188         if (selection)
189           appsvc_add_data(b, APPSVC_DATA_KEYWORD, selection);
190      }
191    appsvc_run_service(b, 0, NULL, NULL);
192    bundle_free(b);
193    _ctxpopup_hide(obj);
194 }
195
196 static void
197 _clipboard_menu(void *data, Evas_Object *obj, void *event_info)
198 {
199    if(!ext_mod) return;
200
201    // start for cbhm
202 #ifdef HAVE_ELEMENTARY_X
203    ecore_x_selection_secondary_set(elm_win_xwindow_get(obj), "",1);
204 #endif
205    ext_mod->cnpinit(data,obj,event_info);
206    elm_cbhm_helper_init(obj);
207    if (ext_mod->cnp_mode != ELM_CNP_MODE_MARKUP)
208      elm_cbhm_send_raw_data("show0");
209    else
210      elm_cbhm_send_raw_data("show1");
211    _ctxpopup_hide(obj);
212    // end for cbhm
213 }
214
215 static void
216 _item_clicked(void *data, Evas_Object *obj, void *event_info)
217 {
218    Elm_Entry_Context_Menu_Item *it = data;
219    Evas_Object *obj2 = it->obj;
220
221    if (it->func) it->func(it->data, obj2, NULL);
222    _ctxpopup_hide(obj);
223 }
224
225 static void
226 _ctxpopup_dismissed_cb(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
227 {
228    if (!ext_mod) return;
229
230    elm_object_scroll_freeze_pop(ext_mod->popup);
231 }
232
233 // module api funcs needed
234 EAPI int
235 elm_modapi_init(void *m)
236 {
237    return 1; // succeed always
238 }
239
240 EAPI int
241 elm_modapi_shutdown(void *m)
242 {
243    return 1; // succeed always
244 }
245
246 // module funcs for the specific module type
247 EAPI void
248 obj_hook(Evas_Object *obj)
249 {
250    _mod_hook_count++;
251    //if(_mod_hook_count > 1) return;
252
253    if(!ext_mod)
254      {
255         ext_mod = ELM_NEW(Elm_Entry_Extension_data);
256         elm_entry_extension_module_data_get(obj,ext_mod);
257      }
258 }
259
260 EAPI void
261 obj_unhook(Evas_Object *obj)
262 {
263    _mod_hook_count--;
264    if(_mod_hook_count > 0) return;
265
266    if(ext_mod)
267      {
268         free(ext_mod);
269         ext_mod = NULL;
270      }
271 }
272
273 EAPI void
274 obj_longpress(Evas_Object *obj)
275 {
276    if(!ext_mod) return;
277
278    Evas_Object *top;
279    const Eina_List *l;
280    const Elm_Entry_Context_Menu_Item *it;
281    const char *context_menu_orientation;
282    char buf[255];
283    Evas_Object* icon;
284    Elm_Object_Item *added_item = NULL;
285
286    /*update*/
287    elm_entry_extension_module_data_get(obj,ext_mod);
288    if (ext_mod->context_menu)
289      {
290 #ifdef HAVE_ELEMENTARY_X
291         int cbhm_count = -1;
292         if (elm_cbhm_helper_init(obj))
293           cbhm_count = elm_cbhm_get_count();
294 #endif
295         if (ext_mod->popup) evas_object_del(ext_mod->popup);
296         //else elm_widget_scroll_freeze_push(obj);
297         top = elm_widget_top_get(obj);
298         if(top)
299           {
300              ext_mod->popup = elm_ctxpopup_add(top);
301              elm_object_tree_unfocusable_set(ext_mod->popup, EINA_TRUE);
302              evas_object_smart_callback_add(ext_mod->popup, "dismissed", _ctxpopup_dismissed_cb, NULL);
303           }
304         /*currently below theme not used,when guideline comes a new theme can be created if required*/
305         elm_object_style_set(ext_mod->popup,"extended/entry");
306         context_menu_orientation = edje_object_data_get
307            (ext_mod->ent, "context_menu_orientation");
308         if ((context_menu_orientation) &&
309             (!strcmp(context_menu_orientation, "horizontal")))
310           elm_ctxpopup_horizontal_set(ext_mod->popup, EINA_TRUE);
311
312         elm_widget_sub_object_add(obj, ext_mod->popup);
313         if (!ext_mod->selmode)
314           {
315              if (!ext_mod->password)
316                {
317                   if (!elm_entry_is_empty(obj))
318                     {
319                        added_item = elm_ctxpopup_item_append(ext_mod->popup, S_SELECT, NULL, _select, obj );
320                        added_item = elm_ctxpopup_item_append(ext_mod->popup, S_SELECT_ALL, NULL, _select_all, obj );
321                     }
322                }
323
324 #ifdef HAVE_ELEMENTARY_X
325              if (cbhm_count)
326 #else
327              if (1) // need way to detect if someone has a selection
328 #endif
329                {
330                   if (ext_mod->editable)
331                     added_item = elm_ctxpopup_item_append(ext_mod->popup, S_PASTE, NULL, _paste, obj );
332                }
333              //elm_ctxpopup_item_append(wd->ctxpopup, NULL, "Selectall",_select_all, obj );
334              // start for cbhm
335 #ifdef HAVE_ELEMENTARY_X
336              if ((!ext_mod->password) && (ext_mod->editable) && (cbhm_count))
337 #else
338              if ((!ext_mod->password) && (ext_mod->editable))
339 #endif
340                {
341                   added_item = elm_ctxpopup_item_append(ext_mod->popup, S_CLIPBOARD, NULL, _clipboard_menu, obj);  // Clipboard
342                   //elm_ctxpopup_item_append(ext_mod->popup, "More", NULL, _clipboard_menu, obj );
343                }
344              // end for cbhm
345              icon = elm_icon_add(ext_mod->popup);
346              snprintf(buf, sizeof(buf), "%s/images/copy&paste_icon_search.png", PACKAGE_DATA_DIR);
347              elm_icon_file_set(icon, buf, NULL);
348              added_item = elm_ctxpopup_item_append(ext_mod->popup, NULL, icon, _search_menu, obj);  // Search
349           }
350         else
351           {
352              if (!ext_mod->password)
353                {
354                   if (ext_mod->have_selection)
355                     {
356                        added_item = elm_ctxpopup_item_append(ext_mod->popup, S_COPY, NULL, _copy, obj );
357                        if (ext_mod->editable)
358                          added_item = elm_ctxpopup_item_append(ext_mod->popup, S_CUT, NULL, _cut, obj );
359 #ifdef HAVE_ELEMENTARY_X
360                        if (ext_mod->editable && cbhm_count)
361 #else
362                        if (ext_mod->editable)
363 #endif
364                          added_item = elm_ctxpopup_item_append(ext_mod->popup, S_PASTE, NULL, _paste, obj );
365                     }
366                   else
367                     {
368                        _cancel(obj,ext_mod->popup,NULL);
369                        if (!elm_entry_is_empty(obj))
370                          {
371                             added_item = elm_ctxpopup_item_append(ext_mod->popup, S_SELECT, NULL, _select, obj );
372                             added_item = elm_ctxpopup_item_append(ext_mod->popup, S_SELECT_ALL, NULL, _select_all, obj );
373                          }
374 #ifdef HAVE_ELEMENTARY_X
375                        if (cbhm_count)
376 #else
377                        if (1) // need way to detect if someone has a selection
378 #endif
379                          {
380                             if (ext_mod->editable)
381                               added_item = elm_ctxpopup_item_append(ext_mod->popup, S_PASTE, NULL, _paste, obj );
382                          }
383                     }
384                   // start for cbhm
385 #ifdef HAVE_ELEMENTARY_X
386                   if (ext_mod->editable && cbhm_count)
387 #else
388                   if (ext_mod->editable)
389 #endif
390                     {
391                        added_item = elm_ctxpopup_item_append(ext_mod->popup, S_CLIPBOARD, NULL, _clipboard_menu, obj);  // Clipboard
392                        //elm_ctxpopup_item_append(ext_mod->popup, "More", NULL, _clipboard_menu, obj );
393                     }
394                   // end for cbhm
395                   icon = elm_icon_add(ext_mod->popup);
396                   snprintf(buf, sizeof(buf), "%s/images/copy&paste_icon_search.png", PACKAGE_DATA_DIR);
397                   elm_icon_file_set(icon, buf, NULL);
398                   added_item = elm_ctxpopup_item_append(ext_mod->popup, NULL, icon, _search_menu, obj);  // Search
399                }
400           }
401         EINA_LIST_FOREACH(ext_mod->items, l, it)
402           {
403              added_item = elm_ctxpopup_item_append(ext_mod->popup, it->label, NULL, _item_clicked, it );
404           }
405         if (ext_mod->popup && added_item)
406           {
407              elm_object_scroll_freeze_push(ext_mod->popup);
408              _ctxpopup_position(obj);
409              evas_object_show(ext_mod->popup);
410              ext_mod->caller = obj;
411              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _entry_move, ext_mod->popup);
412           }
413         else
414           ext_mod->caller = NULL;
415      }
416 }
417
418 EAPI void
419 obj_mouseup(Evas_Object *obj)
420 {
421    if (!obj || !ext_mod)
422      return;
423 }
424
425
426 EAPI void
427 obj_hidemenu(Evas_Object *obj)
428 {
429    if (!obj || !ext_mod || obj != ext_mod->caller)
430      return;
431
432    _ctxpopup_hide(ext_mod->popup);
433    // if (ext_mod->popup) evas_object_del(ext_mod->popup);
434 }