2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.tizenopensource.org/license
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "clipdrawer.h"
20 #include "item_manager.h"
21 #include "xconverter.h"
23 #define EDJ_PATH "/usr/share/edje"
24 #define APP_EDJ_FILE EDJ_PATH"/cbhmdrawer.edj"
25 #define GRP_MAIN "cbhmdrawer"
27 #define ANIM_DURATION 30 // 1 seconds
28 #define ANIM_FLOPS (0.5/30)
29 #define DEFAULT_WIDTH 720
30 #define GRID_IMAGE_INNER 10
32 static Evas_Object *create_win(ClipdrawerData *cd, const char *name);
33 static Evas_Object *_grid_content_get(void *data, Evas_Object *obj, const char *part);
34 static void _grid_del(void *data, Evas_Object *obj);
35 static Eina_Bool clipdrawer_add_item(AppData *ad, CNP_ITEM *item);
36 static Eina_Bool clipdrawer_del_item(AppData *ad, CNP_ITEM *item);
37 static void clipdrawer_ly_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
38 static void _grid_item_ly_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
39 static void setting_win(Ecore_X_Display *x_disp, Ecore_X_Window x_main_win);
40 static void set_transient_for(Ecore_X_Window x_main_win, Ecore_X_Window x_active_win);
41 static void unset_transient_for(Ecore_X_Window x_main_win, Ecore_X_Window x_active_win);
43 static void _change_gengrid_paste_textonly_mode(ClipdrawerData *cd)
45 CNP_ITEM *item = NULL;
47 Elm_Object_Item *gitem = elm_gengrid_first_item_get(cd->gengrid);
51 item = elm_object_item_data_get(gitem);
52 if ((item->type_index == ATOM_INDEX_IMAGE) && (item->layout))
54 if (cd->paste_text_only)
55 edje_object_signal_emit(elm_layout_edje_get(item->layout), "elm,state,show,dim", "elm");
57 edje_object_signal_emit(elm_layout_edje_get(item->layout), "elm,state,hide,dim", "elm");
59 gitem = elm_gengrid_item_next_get(gitem);
63 void clipdrawer_paste_textonly_set(AppData *ad, Eina_Bool textonly)
65 ClipdrawerData *cd = ad->clipdrawer;
66 if (cd->paste_text_only != textonly)
67 cd->paste_text_only = textonly;
68 DTRACE("paste textonly mode = %d\n", textonly);
70 _change_gengrid_paste_textonly_mode(cd);
73 Eina_Bool clipdrawer_paste_textonly_get(AppData *ad)
75 ClipdrawerData *cd = ad->clipdrawer;
76 return cd->paste_text_only;
79 static Evas_Object *_load_edj(Evas_Object* win, const char *file, const char *group)
81 Evas_Object *layout = elm_layout_add(win);
84 DMSG("ERROR: elm_layout_add return NULL\n");
88 if (!elm_layout_file_set(layout, file, group))
90 DMSG("ERROR: elm_layout_file_set return FALSE\n");
91 evas_object_del(layout);
95 evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
96 elm_win_resize_object_add(win, layout);
98 evas_object_show(layout);
102 static Eina_Bool keydown_cb(void *data, int type, void *event)
105 Ecore_Event_Key *ev = event;
106 if (!strcmp(ev->keyname, KEY_END))
107 clipdrawer_lower_view(ad);
109 return ECORE_CALLBACK_PASS_ON;
112 ClipdrawerData* init_clipdrawer(AppData *ad)
114 ClipdrawerData *cd = calloc(1, sizeof(ClipdrawerData));
116 /* create and setting window */
119 if (!(cd->main_win = create_win(cd, APPNAME)))
124 cd->x_main_win = elm_win_xwindow_get(cd->main_win);
125 setting_win(ad->x_disp, cd->x_main_win);
128 if (!(cd->main_layout = _load_edj(cd->main_win, APP_EDJ_FILE, GRP_MAIN)))
130 evas_object_del(cd->main_win);
135 Evas_Object* ly = elm_layout_edje_get(cd->main_layout);
136 if (cd->root_w == DEFAULT_WIDTH)
138 cd->height = atoi(edje_object_data_get(ly, "proxima_clipdrawer_height"));
139 cd->landscape_height = atoi(edje_object_data_get(ly, "proxima_clipdrawer_landscape_height"));
140 cd->grid_item_w = atoi(edje_object_data_get(ly, "proxima_grid_item_w"));
141 cd->grid_item_h = atoi(edje_object_data_get(ly, "proxima_grid_item_h"));
145 cd->height = atoi(edje_object_data_get(ly, "u1_clipdrawer_height"));
146 cd->landscape_height = atoi(edje_object_data_get(ly, "u1_clipdrawer_landscape_height"));
147 cd->grid_item_w = atoi(edje_object_data_get(ly, "u1_grid_item_w"));
148 cd->grid_item_h = atoi(edje_object_data_get(ly, "u1_grid_item_h"));
150 printf("height: %d , land_height:%d\n", cd->height, cd->landscape_height);
152 /* create and setting gengrid */
153 elm_theme_extension_add(NULL, APP_EDJ_FILE);
154 edje_object_signal_callback_add(elm_layout_edje_get(cd->main_layout),
155 "mouse,up,1", "*", clipdrawer_ly_clicked, ad);
157 elm_object_part_text_set(cd->main_layout, "panel_title", "Clipboard");
158 elm_object_part_text_set(cd->main_layout, "panel_function", "Done");
160 cd->gengrid = elm_gengrid_add(cd->main_win);
161 elm_object_part_content_set(cd->main_layout, "historyitems", cd->gengrid);
162 elm_gengrid_item_size_set(cd->gengrid, cd->grid_item_w, cd->grid_item_h);
163 elm_gengrid_align_set(cd->gengrid, 0.0, 0.0);
164 elm_gengrid_horizontal_set(cd->gengrid, EINA_TRUE);
165 elm_gengrid_bounce_set(cd->gengrid, EINA_TRUE, EINA_FALSE);
166 elm_gengrid_multi_select_set(cd->gengrid, EINA_FALSE);
167 // evas_object_smart_callback_add(cd->gengrid, "selected", _grid_click_paste, ad);
168 evas_object_size_hint_weight_set(cd->gengrid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
170 elm_gengrid_clear(cd->gengrid);
172 cd->gic.item_style = "clipboard_photo_style";
173 cd->gic.func.text_get = NULL;
174 cd->gic.func.content_get = _grid_content_get;
175 cd->gic.func.state_get = NULL;
176 cd->gic.func.del = _grid_del;
178 evas_object_show(cd->gengrid);
180 ad->draw_item_add = clipdrawer_add_item;
181 ad->draw_item_del = clipdrawer_del_item;
182 // ad->x_main_win = cd->x_main_win;
184 cd->keydown_handler = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, keydown_cb, ad);
185 cd->evas = evas_object_evas_get(cd->main_win);
187 delete_mode = EINA_FALSE;
192 void depose_clipdrawer(ClipdrawerData *cd)
194 evas_object_del(cd->main_win);
196 ecore_timer_del(cd->anim_timer);
197 if (cd->keydown_handler)
198 ecore_event_handler_del(cd->keydown_handler);
202 static Eina_Bool clipdrawer_add_item(AppData *ad, CNP_ITEM *item)
204 ClipdrawerData *cd = ad->clipdrawer;
205 if (item->type_index == ATOM_INDEX_IMAGE)
207 Elm_Object_Item *gitem = elm_gengrid_first_item_get(cd->gengrid);
210 CNP_ITEM *gitem_data = elm_object_item_data_get(gitem);
211 gitem = elm_gengrid_item_next_get(gitem);
212 if ((gitem_data->type_index == item->type_index) && (!strcmp(item->data, gitem_data->data)))
214 DMSG("duplicated file path = %s\n", item->data);
215 item_delete_by_CNP_ITEM(ad, gitem_data);
220 item->gitem = elm_gengrid_item_prepend(cd->gengrid, &cd->gic, item, NULL, NULL);
225 static Eina_Bool clipdrawer_del_item(AppData *ad, CNP_ITEM *item)
228 elm_object_item_del(item->gitem);
232 static void _grid_del(void *data, Evas_Object *obj)
234 CNP_ITEM *item = data;
239 static Evas_Object *_grid_content_get(void *data, Evas_Object *obj, const char *part)
241 CNP_ITEM *item = data;
242 AppData *ad = item->ad;
243 ClipdrawerData *cd = ad->clipdrawer;
245 if (item->type_index == ATOM_INDEX_IMAGE && !strcmp(part, "elm.swallow.icon")) /* text/uri */
249 Evas_Object *layout = elm_layout_add(obj);
250 elm_layout_theme_set(layout, "gengrid", "item", "clipboard_style");
251 edje_object_signal_callback_add(elm_layout_edje_get(layout),
252 "mouse,up,1", "*", _grid_item_ly_clicked, data);
256 int grid_image_real_w;
257 int grid_image_real_h;
258 grid_image_real_w = cd->grid_item_w - (2*GRID_IMAGE_INNER);
259 grid_image_real_h = cd->grid_item_h - (2*GRID_IMAGE_INNER);
260 sicon = evas_object_image_add(evas_object_evas_get(obj));
261 evas_object_image_load_size_set(sicon, grid_image_real_w, grid_image_real_h);
262 evas_object_image_file_set(sicon, item->data, NULL);
263 evas_object_image_size_get(sicon, &w, &h);
265 if (w > grid_image_real_w || h > grid_image_real_h)
269 iw = grid_image_real_w;
270 ih = (float)grid_image_real_w / w * h;
274 iw = (float)grid_image_real_h / h * w;
275 ih = grid_image_real_h;
284 evas_object_image_fill_set(sicon, 0, 0, iw, ih);
285 evas_object_resize(sicon, iw, ih);
286 evas_object_size_hint_min_set(sicon, iw, ih);
287 elm_object_part_content_set(layout, "elm.swallow.icon", sicon);
289 if (cd->paste_text_only)
290 edje_object_signal_emit(elm_layout_edje_get(layout), "elm,state,show,dim", "elm");
292 edje_object_signal_emit(elm_layout_edje_get(layout), "elm,state,hide,dim", "elm");
294 item->layout = layout;
296 else if (item->type_index != ATOM_INDEX_IMAGE && !strcmp(part, "elm.swallow.entry")) /* text/uri */
298 Evas_Object *layout = elm_layout_add(obj);
299 elm_layout_theme_set(layout, "gengrid", "widestyle", "horizontal_layout");
300 edje_object_signal_callback_add(elm_layout_edje_get(layout),
301 "mouse,up,1", "*", _grid_item_ly_clicked, data);
302 Evas_Object *rect = evas_object_rectangle_add(evas_object_evas_get(obj));
303 evas_object_resize(rect, cd->grid_item_w, cd->grid_item_h);
304 evas_object_color_set(rect, 237, 233, 208, 255);
305 evas_object_show(rect);
306 elm_object_part_content_set(layout, "elm.swallow.icon", rect);
308 Evas_Object *ientry = elm_entry_add(obj);
309 evas_object_size_hint_weight_set(ientry, 0, 0);
310 elm_entry_scrollable_set(ientry, EINA_TRUE);
312 char *entry_text = string_for_entry_get(ad, item->type_index, item->data);
315 elm_object_part_text_set(ientry, NULL, entry_text);
320 elm_object_part_text_set(ientry, NULL, item->data);
322 elm_entry_editable_set(ientry, EINA_FALSE);
323 elm_entry_context_menu_disabled_set(ientry, EINA_TRUE);
324 evas_object_show(ientry);
325 elm_object_part_content_set(layout, "elm.swallow.inner", ientry);
327 item->layout = layout;
333 edje_object_signal_emit(elm_layout_edje_get(item->layout), "elm,state,show,delbtn", "elm");
335 edje_object_signal_emit(elm_layout_edje_get(item->layout), "elm,state,hide,delbtn", "elm");
340 static void clipdrawer_ly_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
344 if (ad->clipdrawer->anim_status != STATUS_NONE)
347 #define EDJE_CLOSE_PART_PREFIX "background/title/close"
348 #define EDJE_DELETE_MODE_PREFIX "background/title/delete"
349 if (!strncmp(source, EDJE_CLOSE_PART_PREFIX, strlen(EDJE_CLOSE_PART_PREFIX)))
351 clipdrawer_lower_view(ad);
353 else if (!strncmp(source, EDJE_DELETE_MODE_PREFIX, strlen(EDJE_DELETE_MODE_PREFIX)))
355 _delete_mode_set(ad, !delete_mode);
360 static void _grid_item_ly_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
362 CNP_ITEM *item = data;
363 AppData *ad = item->ad;
364 ClipdrawerData *cd = ad->clipdrawer;
366 if (cd->anim_status != STATUS_NONE)
369 Elm_Object_Item *sgobj = NULL;
370 sgobj = elm_gengrid_selected_item_get(cd->gengrid);
371 item = elm_object_item_data_get(sgobj);
375 DTRACE("ERR: cbhm can't get the selected item\n");
379 #define EDJE_DELBTN_PART_PREFIX "delbtn"
380 if (strncmp(source, EDJE_DELBTN_PART_PREFIX, strlen(EDJE_DELBTN_PART_PREFIX)))
382 elm_gengrid_item_selected_set(sgobj, EINA_FALSE);
387 if (item->type_index != ATOM_INDEX_IMAGE || !cd->paste_text_only)
389 set_selection_owner(ad, ECORE_X_SELECTION_SECONDARY, item);
394 elm_gengrid_item_selected_set(sgobj, EINA_FALSE);
396 item_delete_by_CNP_ITEM(ad, item);
400 void set_transient_for(Ecore_X_Window x_main_win, Ecore_X_Window x_active_win)
402 ecore_x_icccm_transient_for_set(x_main_win, x_active_win);
403 ecore_x_event_mask_set(x_active_win,
404 ECORE_X_EVENT_MASK_WINDOW_PROPERTY | ECORE_X_EVENT_MASK_WINDOW_CONFIGURE);
407 void unset_transient_for(Ecore_X_Window x_main_win, Ecore_X_Window x_active_win)
409 ecore_x_event_mask_unset(x_active_win,
410 ECORE_X_EVENT_MASK_WINDOW_PROPERTY | ECORE_X_EVENT_MASK_WINDOW_CONFIGURE);
411 ecore_x_icccm_transient_for_unset(x_main_win);
414 static void set_focus_for_app_window(Ecore_X_Window x_main_win, Eina_Bool enable)
417 Eina_Bool accepts_focus;
418 Ecore_X_Window_State_Hint initial_state;
419 Ecore_X_Pixmap icon_pixmap;
420 Ecore_X_Pixmap icon_mask;
421 Ecore_X_Window icon_window;
422 Ecore_X_Window window_group;
425 ecore_x_icccm_hints_get (x_main_win,
426 &accepts_focus, &initial_state, &icon_pixmap, &icon_mask, &icon_window, &window_group, &is_urgent);
427 ecore_x_icccm_hints_set (x_main_win,
428 enable, initial_state, icon_pixmap, icon_mask, icon_window, window_group, is_urgent);
429 DMSG("set focus mode = %d\n", enable);
432 void setting_win(Ecore_X_Display *x_disp, Ecore_X_Window x_main_win)
435 // disable window effect
436 utilx_set_window_effect_state(x_disp, x_main_win, 0);
438 ecore_x_icccm_name_class_set(x_main_win, "NORMAL_WINDOW", "NORMAL_WINDOW");
440 set_focus_for_app_window(x_main_win, EINA_FALSE);
444 Evas_Object *create_win(ClipdrawerData *cd, const char *name)
448 Evas_Object *win = elm_win_add(NULL, name, ELM_WIN_BASIC);
451 DMSG("ERROR: elm_win_add return NULL\n");
454 elm_win_title_set(win, name);
455 elm_win_borderless_set(win, EINA_TRUE);
456 ecore_x_window_size_get(ecore_x_window_root_first_get(), &cd->root_w, &cd->root_h);
457 DMSG("root_w: %d, root_h: %d\n", cd->root_w, cd->root_h);
458 evas_object_resize(win, cd->root_w, cd->root_h);
460 elm_scale_set((double)cd->root_w/DEFAULT_WIDTH);
464 static void set_sliding_win_geometry(ClipdrawerData *cd)
468 Evas_Coord x, y, w, h;
469 zone = ecore_x_e_illume_zone_get(cd->x_main_win);
470 DTRACE(" zone:%x\n", zone);
472 if (cd->o_degree == 90 || cd->o_degree == 270)
474 h = cd->anim_count * cd->landscape_height / ANIM_DURATION;
481 h = cd->anim_count * cd->height / ANIM_DURATION;
490 DTRACE("[CBHM] change degree geometry... (%d, %d, %d x %d)\n", x, y, w, h);
493 clipboard_state = ECORE_X_ILLUME_CLIPBOARD_STATE_ON;
495 clipboard_state = ECORE_X_ILLUME_CLIPBOARD_STATE_OFF;
496 ecore_x_e_illume_clipboard_geometry_set(zone, x, y, w, h);
497 ecore_x_e_illume_clipboard_state_set(zone, clipboard_state);
500 void set_rotation_to_clipdrawer(ClipdrawerData *cd)
503 int angle = cd->o_degree;
506 if (angle == 180) // reverse
513 else if (angle == 90) // right rotate
515 h = cd->landscape_height;
520 else if (angle == 270) // left rotate
522 h = cd->landscape_height;
535 evas_object_resize(cd->main_win, w, h);
536 evas_object_move(cd->main_win, x, y);
537 if (cd->anim_count == ANIM_DURATION)
538 set_sliding_win_geometry(cd);
541 static Eina_Bool _get_anim_pos(ClipdrawerData *cd, int *sp, int *ep)
546 int angle = cd->o_degree;
547 int anim_start, anim_end;
549 if (angle == 180) // reverse
551 anim_start = -(cd->root_h - cd->height);
554 else if (angle == 90) // right rotate
556 anim_start = cd->root_w;
557 anim_end = anim_start - cd->landscape_height;
559 else if (angle == 270) // left rotate
561 anim_start = -(cd->root_w - cd->landscape_height);
566 anim_start = cd->root_h;
567 anim_end = anim_start - cd->height;
575 static Eina_Bool _do_anim_delta_pos(ClipdrawerData *cd, int sp, int ep, int ac, int *dp)
580 int angle = cd->o_degree;
583 posprop = 1.0*ac/ANIM_DURATION;
585 if (angle == 180) // reverse
587 delta = (int)((ep-sp)*posprop);
588 evas_object_move(cd->main_win, 0, sp+delta);
590 else if (angle == 90) // right rotate
592 delta = (int)((ep-sp)*posprop);
593 evas_object_move(cd->main_win, sp+delta, 0);
595 else if (angle == 270) // left rotate
597 delta = (int)((ep-sp)*posprop);
598 evas_object_move(cd->main_win, sp+delta, 0);
602 delta = (int)((sp-ep)*posprop);
603 evas_object_move(cd->main_win, 0, sp-delta);
611 static void stop_animation(AppData *ad)
614 ClipdrawerData *cd = ad->clipdrawer;
615 cd->anim_status = STATUS_NONE;
618 ecore_timer_del(cd->anim_timer);
619 cd->anim_timer = NULL;
622 set_sliding_win_geometry(cd);
625 static Eina_Bool anim_pos_calc_cb(void *data)
628 ClipdrawerData *cd = ad->clipdrawer;
629 int anim_start, anim_end, delta;
631 _get_anim_pos(cd, &anim_start, &anim_end);
633 if (cd->anim_status == SHOW_ANIM)
635 if (cd->anim_count > ANIM_DURATION)
637 cd->anim_count = ANIM_DURATION;
641 _do_anim_delta_pos(cd, anim_start, anim_end, cd->anim_count, &delta);
642 if (cd->anim_count == 1)
643 evas_object_show(cd->main_win);
646 else if (cd->anim_status == HIDE_ANIM)
648 if (cd->anim_count < 0)
651 evas_object_hide(cd->main_win);
652 elm_win_lower(cd->main_win);
653 unset_transient_for(cd->x_main_win, ad->x_active_win);
655 _delete_mode_set(ad, EINA_FALSE);
658 _do_anim_delta_pos(cd, anim_start, anim_end, cd->anim_count, &delta);
670 static Eina_Bool clipdrawer_anim_effect(AppData *ad, AnimStatus atype)
673 ClipdrawerData *cd = ad->clipdrawer;
674 if (atype == cd->anim_status)
676 DTRACE("Warning: Animation effect is already in progress. \n");
680 cd->anim_status = atype;
683 ecore_timer_del(cd->anim_timer);
684 cd->anim_timer = ecore_timer_add(ANIM_FLOPS, anim_pos_calc_cb, ad);
689 void clipdrawer_activate_view(AppData* ad)
692 ClipdrawerData *cd = ad->clipdrawer;
695 set_focus_for_app_window(cd->x_main_win, EINA_TRUE);
696 set_transient_for(cd->x_main_win, ad->x_active_win);
697 cd->o_degree = get_active_window_degree(ad->x_active_win);
698 elm_win_rotation_set(cd->main_win, cd->o_degree);
699 set_rotation_to_clipdrawer(cd);
700 evas_object_show(cd->main_win);
701 elm_win_activate(cd->main_win);
702 clipdrawer_anim_effect(ad, SHOW_ANIM);
706 void clipdrawer_lower_view(AppData* ad)
709 ClipdrawerData *cd = ad->clipdrawer;
710 if (cd->main_win && cd->anim_count)
712 set_focus_for_app_window(cd->x_main_win, EINA_FALSE);
713 // if (clipdrawer_anim_effect(ad, HIDE_ANIM))
714 // ad->windowshow = EINA_FALSE;
715 clipdrawer_anim_effect(ad, HIDE_ANIM);
719 void _delete_mode_set(AppData* ad, Eina_Bool del_mode)
721 ClipdrawerData *cd = ad->clipdrawer;
722 CNP_ITEM *item = NULL;
724 delete_mode = del_mode;
727 edje_object_signal_emit(elm_layout_edje_get(cd->main_layout), "elm,state,show,function", "elm");
728 edje_object_signal_emit(elm_layout_edje_get(cd->main_layout), "elm,state,hide,delmode", "elm");
732 edje_object_signal_emit(elm_layout_edje_get(cd->main_layout), "elm,state,hide,function", "elm");
733 edje_object_signal_emit(elm_layout_edje_get(cd->main_layout), "elm,state,show,delmode", "elm");
736 Elm_Object_Item *gitem = elm_gengrid_first_item_get(cd->gengrid);
739 item = elm_object_item_data_get(gitem);
741 edje_object_signal_emit(elm_layout_edje_get(item->layout), "elm,state,show,delbtn", "elm");
743 edje_object_signal_emit(elm_layout_edje_get(item->layout), "elm,state,hide,delbtn", "elm");
745 gitem = elm_gengrid_item_next_get(gitem);